OMGDB treats error messages as part of the agent surface. Every error is deterministic, names the exact offending token or field, and — wherever a typo is plausible — carries a did-you-mean hint computed by edit distance against the real vocabulary. An AI agent (or a human) can read the message and repair the call without consulting anything else. This page catalogs the messages the engine actually produces, grouped by surface, with the exact strings.
On the CLI these arrive on stderr with a non-zero exit; over MCP the same strings come back as tool results flagged isError: true.
Unknown operators
The engine never answers a misspelled operator with a generic parse failure. Each of the three operator vocabularies — query, update, aggregation — rejects unknown tokens by name, with a suggestion when a known operator is within edit distance 2.
A typo in a query filter:
unknown query operator: $gtee (did you mean `$gte`?)
A typo in an update document (plan-update, MCP plan_update):
unknown update operator: $sett (did you mean `$set`?)
Typos in an aggregation pipeline are qualified by where they occurred — a stage, an accumulator, or an expression:
unknown aggregation operator: $sortt (stage) (did you mean `$sort`?)
unknown aggregation operator: $frist (accumulator) (did you mean `$first`?)
unknown aggregation operator: $toUppr (did you mean `$toUpper`?)
The same treatment extends into operator arguments. $type checks its type names, and it refuses names that would silently match nothing — OMGDB stores integers as long, so int is redirected instead of compiled into an always-false predicate:
malformed query: $type: unknown type name `strin` (did you mean `string`?)
malformed query: $type: OMGDB stores no `int` values (integers are `long`); use `long`, `double`, or `number`
If no known token is close enough, the error simply names the bad operator (for example unknown update operator: $bogus).
Missing collections
A typo’d collection name must never produce confidently wrong output, so the two introspection commands that give advice — explain and diagnose — fail loudly, listing what does exist:
collection `ticket` does not exist — did you mean `tickets`? (existing: tickets, users)
On an empty store the variant is:
collection `ticket` does not exist (the store has no collections yet)
find is different by design: it keeps MongoDB’s semantics, where querying a missing collection returns an empty result and exits zero. But an agent should still hear about the likely typo, so the hint goes to stderr as a warning while stdout stays empty:
warning: collection `ticket` does not exist — did you mean `tickets`?
Validation errors
Writes into a collection with a validation spec are checked before anything is appended. Every failure is wrapped as validation failed for : <reason>.
A required field is absent:
validation failed for `users`: missing required field `name`
A field has the wrong type (number accepts both integers and doubles; every other name is exact):
validation failed for `users`: field `age` should be `long` but is `string`
A declared reference points at a document that does not exist:
validation failed for `posts`: field `author` references missing `users._id` {"$oid":"018f2f4c9d1e4a0b8c000001"}
The spec itself is validated at define time, not at first insert. A spec with an unknown field type would reject every future write, so define fails immediately and lists the entire accepted vocabulary:
validation failed for `users`: field `age` has unknown type `integer` (expected one of: array, binData, bool, date, double, long, markdown, null, number, object, objectId, string)
Unique and _id conflicts
Inserting a document whose _id already exists in the collection (the _id is echoed in canonical JSON):
duplicate _id in `users`: {"$oid":"018f2f4c9d1e4a0b8c000001"}
Violating a unique index reports the collection, the indexed field, and the conflicting value:
unique index violation on `users.email` for value "[email protected]"
For a compound unique index the fields are comma-joined and the value is the conflicting tuple:
unique index violation on `users.org,email` for value ["acme","[email protected]"]
The same check runs when the index is created: a unique index over existing data that already contains duplicates fails with this error rather than building a broken index.
Corruption, CRC, and repair
Every op-log record carries a CRC-32 and a dense LSN, verified on every read. The default open path is fail-stop: corruption is reported, never silently skipped.
log corruption: line 3: CRC mismatch
log corruption: line 3: lsn 4 (expected 2)
log corruption: a complete record contains invalid UTF-8
Note: A torn tail is not corruption. If a write was interrupted mid-append (a crash, a kill), the incomplete trailing fragment is preserved to
oplog.torn.bakand the log is trimmed to its durable prefix automatically on the next open — no data that was ever acknowledged is touched. Corruption means a complete record fails its checks.
Recovery from genuine corruption is opt-in, through omgdb repair. With no flags it is a non-destructive dry run:
omgdb repair app.omgdb
CORRUPT at byte 412 of 897: CRC mismatch
recoverable prefix: 3 record(s)
re-run with `--truncate --yes` to drop the corrupt tail (a backup is kept)
The recoverable prefix always ends on a record boundary. To actually truncate to it, both flags are required (--truncate alone refuses with refusing to modify the log without `--yes` ), and the original file — including the corrupt tail — is backed up first:
omgdb repair app.omgdb --truncate --yes
CORRUPT at byte 412 of 897: CRC mismatch
recoverable prefix: 3 record(s)
repaired: kept 3 record(s); corrupt original backed up to app.omgdb/oplog.ndjson.corrupt.bak
On an intact log, repair says so and does nothing:
OK: log is intact (12 record(s)); nothing to repair
Run omgdb verify app.omgdb afterwards — it re-proves that the log reproduces the full state, including every derived cache. See storage for the durability model behind all of this.
Store lock
A store is single-process: opening it takes an exclusive advisory lock, and a second process is refused cleanly rather than corrupting anything:
store at `app.omgdb` is locked by another process
repair checks the same lock before touching the raw log, with its own guidance:
store at `app.omgdb` is locked by another process; close it before repairing
Recovery is simply to close the other process — the lock is released the moment the holding process exits, even if it crashed. If you are running the MCP server, note that it takes the lock only for the duration of each tool call, so a persistent lock error points at some other long-lived holder.
Related
- Connect your coding agent — wiring these errors into an agent’s repair loop over MCP.
- Schema validation — the spec vocabulary behind the validation errors.
- Storage & op-log — CRC framing, torn-tail recovery, and the fail-stop open path.
- CLI reference — the full
repairandverifycommand documentation.