Skip to content

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; watched
Hint: 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.

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.

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