Overview#
A diagnostic code is a stable identifier at the start of a message, such as TERSE-STO-001 or TERSE028. This page lists the codes TERSL/DB writes on the wire and what to do about each, names the codes that appear only in the account's log, and lists the TERSL language diagnostics the engine reports.
Codes appear in three places:
- in the Messages channel of a
200answer from the Issue route, aserror: declarations: TERSE-SEC-001: …orerror: queries line 4: TERSE904: …; - in the first line of a refusal's body, as
error: TERSE-STO-001: …; - in the streamed answer of
/load, both aserror:lines and in thereasonof arefusedsummary.
Codes of the form TERSE-AREA-nnn are TERSL/DB's own. Codes of the form TERSE followed by three digits belong to the open TERSL specification. A refusal whose body has no code is described by its sentence; see Status codes.
Access#
| Code | Where | Meaning | What to do |
|---|---|---|---|
TERSE-SEC-001 |
Messages of a 200: error: declarations: TERSE-SEC-001: <Right> at '<path>' is not permitted |
The key's grants do not allow that write at that path. The declarations were not applied. | Ask the namespace's admin for the right, or write somewhere the key may write. See Keys, grants and visibility. |
TERSE-SEC-001 |
The /load stream, before any batch: error: TERSE-SEC-001: Add at '<path>' is not permitted; nothing was processed |
The key can add or modify nothing under a root the file writes. Nothing was applied. | As above. |
A read the grants do not allow has no code: the answer leaves out what the key may not see.
Store#
| Code | Status | Meaning | What to do |
|---|---|---|---|
TERSE-STO-001 |
503 |
The write lost every attempt to commit because of concurrent writes. Nothing was committed. Terse-Csn gives the head that stands. |
Retry after Retry-After. |
TERSE-STO-002 |
422 |
A structural directive, such as [WAS], [REMOVED], [MOVED] or a placement, cannot be carried out as written. Nothing was committed. |
Rewrite the declaration as the message says. |
TERSE-STO-003 |
500 |
The write failed at or after its commit point and may have committed at the CSN the message names. | Resend with the same Terse-Idempotency-Key, or read the head and resend with Expected-Csn. See When the outcome is unknown. |
Idempotency#
| Code | Status | Meaning | What to do |
|---|---|---|---|
TERSE-IDM-001 |
422 |
The Terse-Idempotency-Key was already used for a different body, committed at the CSN the message names. Nothing was committed. |
Send a new key for a new write. On /load, a different batch size plans different batches, so it needs a new key too. |
Content limits#
The content limits bound the size of one value in a write. Every size is counted in UTF-8 bytes, after line endings are normalised to LF. The limits are the deployment's and do not vary by plan. A TERSE-LIM refusal is a 413 with no Retry-After; the whole Issue is refused, nothing is applied and no query is answered. The body carries Terse-Diagnostics: errors=1; warnings=0 and no Terse-Csn.
| Code | What is measured |
|---|---|
TERSE-LIM-001 |
A structural line: every line outside a """ text block, in either half of the Issue, including headers with their paths, directives, query lines, comments and one-line "…" values. Lines inside a block are not counted; the fences are. |
TERSE-LIM-002 |
A name: each segment of a path is one name and is judged on its own. |
TERSE-LIM-003 |
A header payload: a node's name and attribute list as the canonical form writes them, plus the line end. Heading marks, indentation and any path prefix are not counted, so the depth of a node does not decide whether it fits. |
TERSE-LIM-004 |
A text value after the write applies, including an [APPEND], as content bytes. The same limit applies whether the value was written as "…" or as a """ block. |
The message names the limit and its value, the measured size, the node's path or the half and line number, and quotes up to about 80 bytes of the content:
error: TERSE-LIM-001: queries line 2 is N bytes; MaxStructuralLineBytes is L; nothing was processed. It begins "? Places [WHERE…"
To fix a TERSE-LIM refusal, change the value: use a """ block instead of a long line, shorten the name, move attributes into content, or split the value across nodes. Splitting the request does not help, because an [APPEND] is judged on the value it produces. A value already stored over a limit stays readable; a write is refused only when it would make a value both over the limit and larger than it was.
Structural lines are judged first, before the grants. Names, header payloads and text values are judged after the grants, so a key that may not write a path receives TERSE-SEC-001 for it, not a size.
Load#
| Code | Where | Meaning | What to do |
|---|---|---|---|
TERSE-LOAD-001 |
413 before the body, or in the stream |
The load body is over the deployment's load limit. Nothing was applied. | Load a smaller file, or split it into several loads. |
TERSE-LOAD-002 |
503 on other requests |
An exclusive load is running on the namespace. writes refuses Issues with declarations; all also refuses reads and history. |
Retry after Retry-After. |
TERSE-LOAD-003 |
409 |
A load is already running on the namespace. | Wait for it to finish. |
TERSE-LOAD-004 |
503 |
The service is running as many loads as it allows. | Retry after Retry-After. |
TERSE-LOAD-005 |
503 |
The account already has a load running. | Retry after Retry-After, or wait for the other load. |
TERSE-LOAD-006 |
in the stream | The service refused the file before applying anything. The stream lists every refusal with its file line. | Fix the lines named and send the file again. |
A file is refused with TERSE-LOAD-006 for invalid UTF-8, a """ block that is never closed, a structural line or a name over its content limit, a ? line, a wildcard header or a splice, or a stretch of the file with no legal place to cut it into batches. A refusal in the stream is followed by refused csn none wall N s reason <code> and committed through line 0.
Request#
| Code | Status | Meaning | What to do |
|---|---|---|---|
TERSE-REQ-001 |
504 |
The request did not answer within the deployment's request time limit. If the body ends ; nothing was processed, the request was not processed. Otherwise the write may have been applied, and it is recorded when it lands. |
Find out whether it landed before resending; see When the outcome is unknown. |
Codes in the account's log only#
Some refusals are recorded in the account's log with a code, while their body on the wire is a sentence without one. Search the log on the Logs page for these:
| Code | Log event | Wire answer |
|---|---|---|
TERSE-ADM-001, TERSE-ADM-002, TERSE-ADM-003 |
request.throttled |
429 or 503: too many requests in flight for the namespace, the account or the deployment |
TERSE-ADM-004 |
request.throttled |
503: the deployment is at its memory limit |
TERSE-GOV-001, TERSE-GOV-002, TERSE-GOV-006, TERSE-GOV-007, TERSE-GOV-008 |
request.throttled |
429: a rate window of the plan refused the request |
TERSE-GOV-003 |
request.too_large |
413: the body is over the plan's request-size limit |
TERSE-GOV-005 |
request.storage_full |
507: the namespace is at the plan's namespace-size limit |
TERSE-REC-001 |
record.level.refused |
a write refused because of the namespace's record level |
TERSE-ACCT-001 |
request.suspended |
403: the account is suspended |
Language diagnostics#
The TERSL engine reports problems in the text it reads with the specification's codes, TERSE001 to TERSE046 and TERSE901 to TERSE931, and the non-numeric TERSE_QUERY_ERR. They appear in the Messages channel with the channel and line they belong to, keeping their code and text: an error as error:, anything else as warn:. Line numbers in a /load stream are the file's.
An error drops only the unit it names: a line, or a header and the subtree beneath it, while the rest of the request is applied. An error: line in a 200 therefore does not mean nothing was committed; Terse-Csn says whether the head moved. The full text of each code is in section 13, "Diagnostic Codes", of the specification in the open-source repository, terse-lang/terse (terse-spec/TERSE_Specification.md). The table lists the codes the TERSL/DB engine emits.
| Code | Severity | Raised by | What is ignored |
|---|---|---|---|
TERSE001 |
error | an unbalanced or stray (, ), [ or ], or a directive tail missing its ] |
the line, and a header's subtree |
TERSE002 |
error | an unclosed string | the line |
TERSE005 |
warning | a + prefix in an attribute list |
nothing |
TERSE009 |
error | an empty segment, ;;, in a list |
the empty segment |
TERSE013 |
error | a bracketed flag with no name | the segment |
TERSE014 |
warning | the same identifier key twice in one list | nothing; the last wins |
TERSE021 |
error | a name, segment or key that reduces to an empty handle | the header and subtree, the object line, or the key segment |
TERSE022 |
error | a ?Name segment in a query path |
the query line |
TERSE025 |
error | a malformed [WHEN] |
the expression selects nothing |
TERSE026 |
warning | an unknown escape inside "…" |
nothing; both characters are kept |
TERSE027 |
error | an unclosed """ block, or text after """ on the opening line |
the block |
TERSE028 |
error | a forbidden character in a name, two @ references on one line, or attributes after a reference |
the header and subtree, the object line, the key segment, or the query line |
TERSE030 |
error | a " where no value starts, or text after a closing quote |
the character is kept; the trailing text is discarded |
TERSE031 |
warning | a name that collides with a node already present | nothing; the existing node and its display name are kept |
TERSE032 |
warning | a placement anchor that is not an earlier sibling of the same kind | the node is not moved |
TERSE034 |
error | more than one placement directive on a line | the last one wins |
TERSE036 |
error | the retired parenthesised form WAS(…), AS(…), WHERE(…) or WHEN(…), or a capitalised directive after a query path without brackets |
the header and subtree, the object line, or the query line |
TERSE037 |
error | # in a query path segment |
the query line |
TERSE039 |
error | an empty directive tail, [] |
the tail |
TERSE040 |
error | an unknown directive keyword | that segment |
TERSE045 |
warning | a second text value on one node that is not an append | the first value |
TERSE046 |
error | TEXT used where it is reserved |
the header and subtree, the line, or the expression |
TERSE901 |
warning | a [WAS Old] that matches nothing, where the new name does not exist either |
the declaration |
TERSE902 |
error | [WAS] on a query line |
the query line |
TERSE903 |
error | a byte-order mark at the start of a line other than the first | nothing; the line is read as its bytes say |
TERSE904 |
error | a * in the middle of a query path on a read |
the expression |
TERSE906 |
error | a whole-segment * in a header where a wildcard is not allowed |
the header and subtree |
TERSE907 |
warning | a wildcard header, splice, (*) or [FROM] that matched nothing |
nothing was done |
TERSE908 |
warning | a [WHERE] on a wildcard header or shape line that does not compile |
it matches nothing |
TERSE910 |
warning | an [AS] that matched more than one node |
the first match is used |
TERSE911 |
error | an illegal wildcard header: two wildcards, a query directive other than WHERE, or a mutation directive |
the header and its block |
TERSE912 |
error | a directive a ? command cannot carry out |
the line |
TERSE913 |
error | [AS] on a declaration |
the header and subtree, or the line |
TERSE915 |
error | the root header with a directive other than [REMOVED] |
the line and subtree |
TERSE916 |
error | a ## or deeper header with no name |
the line and subtree |
TERSE917 |
error | [CONTAINERS] or [OBJECTS] on a command without a wildcard |
the line |
TERSE918 |
error | [CONTAINERS] or [OBJECTS] on a declaration header |
the header and its block |
TERSE919 |
error | [OBJECTS] together with [CONTAINERS] |
the line |
TERSE920 |
error | an anchored placement on a wildcard command without a kind selector | the line |
TERSE921 |
error | a literal * outside a string |
the line, and a header's subtree |
TERSE922 |
error | a directive tail on an object splice | the line |
TERSE923 |
error | a second […] group on a line |
the line |
TERSE924 |
error | [CONTAINERS n] or [OBJECTS n] |
the line |
TERSE925 |
error | a line in a shape block that is not a shape line, two wildcards in a shaping path, or a line under a * |
the line and its body, or the block |
TERSE926 |
error | a malformed [FROM] path |
the line and its body |
TERSE927 |
error | a classifier line with no anchor it can reach | the line |
TERSE928 |
warning | a ? with a placement or sizing directive that owns a body; it places rather than shapes |
nothing; the body stays ordinary declarations |
TERSE929 |
warning | a shape body that reads the children of an object binding | those lines |
TERSE931 |
warning | a [WHERE] on a read that does not compile |
the expression selects nothing |
TERSE_QUERY_ERR |
error | ?Foo with no space, a malformed [DEPTH], [REMOVED] with a copy directive, or [NEW] with [FILL] |
the query line or the expression |
The language itself is described in Reading with queries and Writing with declarations.