Errors
Every error of the engine says three things: what is wrong (error), how to fix it (hint) and where to read more (docs, a page of this site in Markdown, with its anchor). The HTTP API sends them as JSON fields; the MCP server and DatanotesError end the text with a Hint: and a Docs: line. The docs line of DatanotesError gives the address, then the read_docs call that reads the same section offline; datanotes mcp gives only the call:
insert_row refused — nothing was written:invalid datanotes/main/public/film/Sunrise.md: status must be one of: to watch; watchedHint: Use one of the allowed values listed in the message, written exactly; describe_table shows what each one means. To add a value, alter_column the enum.Docs: https://datanotes.dev/guides/database-objects/columns.md#describe-what-each-enum-value-means (offline: read_docs("guides/database-objects/columns#describe-what-each-enum-value-means"))Read the engine’s errors shows how an agent uses them.
Kinds of error
Section titled “Kinds of error”| Error | Status | The hint gives | Docs |
|---|---|---|---|
| Unknown tool or operation | MCP tool error; 400 | The closest tools | Operations |
| Argument unknown, missing or of the wrong type | MCP tool error, before the call | The argument meant, and the tool’s arguments with their types | The operation’s reference |
| Bad input to an operation or a route | 400 | Its own where the answer is data, else the operation’s arguments | The topic’s page, or the operation’s reference |
| Table or view not found | 404 | The closest names and aliases, the tables and views, or the view’s table where a table is needed | Find the table that matches a request, Store a query as a view |
| Ambiguous table name | 409 | The full names | Place tables in catalogs and schemas |
| Unknown column | 400 | The closest column, the table’s columns, describe_table and add_column |
Describe a table before writing to it |
| Unknown filter operator | 400 | The operator meant, every operator, and the shape of a condition | Compare values with operators |
| Bad expression or aggregate | 400 | The columns and the shape | Group rows and compute totals |
| Unknown base, constraint, catalog, schema, enum value or link column | 400 | The closest name, the list, and the operation that lists them | The topic’s page |
| A name that isn’t an identifier | 400 | The name it could be | Place tables in catalogs and schemas |
| A table, base or column without a description, or one removed | 400 | Every missing description, and the call’s shape with each in place | Describe every table and column |
| Row not found | 400 | The closest note name, and how to find a row’s path or id |
Update one row |
| A value breaks a rule (a violation) | 422 | The hint of its kind: Violations | The page of its kind |
A conflict: expect, linked rows, rows that break a new CHECK, a column others read, cascade, a name taken, merge keys |
422 | What the conflict means and what to do | Guard a write against concurrent edits with expect, Delete a row that other notes link to, Enforce rules with CHECK constraints, Drop a table and archive its rows, Insert or update rows with merge_rows |
| A write that failed partway, rolled back by the engine | 503, with the result as the body | Free the file, then send the write again | The engine rolls back a write it cannot finish |
| A write that failed partway, and its rollback too | 500, with the result as the body | undo_migration |
Undo a write |
| Undo refused, or migration not found | 409, 404 | Undone already, the later changes, list_migrations |
Undo a write, Undo refuses to overwrite later changes |
| No history, no such version, a time before the table existed | 400 | alter_table with history: "on", describe_history, timestamp |
Turn history on for a table, List the versions of a table |
| A batch with an operation refused or unknown | 422, 400 | Each operation’s own; fix it and send the whole batch again | Group several writes with batch |
| A token beyond its permissions | 403 | The permissions, and who changes them | Choose what a token can do |
| Token missing or wrong | 401 | Which token to send, as a bearer token | Authenticate your requests |
| Unknown operation, route, argument, method or body | 404, 400, 405 | The closest operation, route or argument, and the routes in openapi.json |
Call the engines routes |
| Note or folder not found | 404 | Vault paths, list_folder and search_notes |
Read a note |
| Change feed, webhooks or semantic search off | 400, 503 | How to turn it on | Follow every change with the change feed, Turn on semantic search |
| Engine unreachable | Thrown by the client; 502 from the MCP server | Start the engine, or check its address | How the mcp server reaches the engine |
| The engine can’t listen: a port in use or reserved, an address of another machine | Exit code 1 of datanotes serve |
Another --port, --port 0, or an address of this machine |
Choose the port |
| A request while the engine stops | 503 | Wait for the stop, then start the engine again | Stop the engine |
| Unexpected error | 500 | None: it isn’t a mistake of the caller | None |
A refused write writes nothing, so the caller can fix the call and send it again. Hand edits that break a rule aren’t errors: check_table and the change feed report them as violations.
Violations
Section titled “Violations”A write the engine refuses lists its violations, each with a code; check_table and the change feed report the violations of hand edits with the same codes.
| Code | Hint | Docs |
|---|---|---|
required |
Give a value to every required column; describe_table marks them (required: true) and lists an enum’s values. | Describe a table before writing to it |
type |
Give each value the column’s type (describe_table shows it): numbers unquoted, dates as YYYY-MM-DD, links as “[[Note]]”, lists as JSON arrays. | Create a table with typed columns |
enum |
Use one of the allowed values listed in the message, written exactly; describe_table shows what each one means. To add a value, alter_column the enum. | Describe what each enum value means |
vocabulary |
Use one of the values listed in the message, or first insert the new value as a row of the vocabulary table. | Take allowed values from another table |
min |
Give a value inside the column’s range (the message names the bound); describe_table shows its min and max. | Describe a table before writing to it |
max |
Give a value inside the column’s range (the message names the bound); describe_table shows its min and max. | Describe a table before writing to it |
step |
Give a multiple of the column’s step (describe_table shows it). | Describe a table before writing to it |
broken_link |
Link to a note that exists, as “[[Note name]]”: list_link_targets(table, column) lists the rows the column may point to. | Point a column to a row of another table |
ref |
Link to a row of the table the column points to (its ref) that its ref_where / ref_by allow: list_link_targets(table, column) lists them. | Limit link targets with ref_by and ref_where |
unique |
Another row already has this value: choose another one, or update that row instead (select_rows finds it). | Update one row |
unknown_column |
Write only the table’s columns: describe_table lists them. To keep a new front matter key, add_column first. | Describe a table before writing to it |
check |
The row breaks a CHECK constraint of the table (named in the message, with its rule): change the values so the rule holds. describe_table lists the table’s constraints. | Enforce rules with CHECK constraints |
generated |
A generated column is computed by the engine: do not write it; recompute_columns sets it again. | Recompute generated columns after a hand edit |
cycle |
A row cannot be its own ancestor: point the hierarchy column to a row that is not below this one. | Build a tree of rows with a parent link |
inverse |
Both sides of a two-way link must agree: write one side, or run align_relations to repair them. | Repair two-way links with align_relations |
unreadable |
The note’s front matter is not valid YAML (the message quotes the parser), so every read leaves the row out: open the note and fix the YAML, such as a quote or bracket left open or a line without key: value. read_note shows its text. |
Find rows whose front matter can’t be read |