Troubleshooting
If something isn’t working, it’s probably one of these.
“Cannot read or find Context file’AppContext.js’”#
The migration CLI resolves a context by file name. Your context must live in a file matching the name you pass:
# file must be named AppContext.js
masterrecord enable-migrations AppContext“The ‘path’ argument must be of type string”#
You passed an inline config object to env() on a version older than 1.3.0. Upgrade, or use the environment-file form.
SQLite tries to create /db at the filesystem root#
Your connection starts with a leading slash. Use a relative path so it resolves under the project root:
{ "AppContext": { "type": "better-sqlite3", "connection": "db/" } }“near ‘)’: syntax error” when migrating#
Your entity defined fields as constructor object-literals instead of builder methods, so no columns were registered. Define fields as methods:
id(db) { db.integer().primary().auto(); } // ✅
title(db){ db.string(); } // ✅Configuration missing settings for context#
Your env JSON isn’t keyed by the context class name. Wrap settings under the context key:
{ "AppContext": { "type": "postgres", "host": "..." } }“ERR_INVALID_MODULE_SPECIFIER” on Linux after migrating on Windows#
A migration snapshot generated on Windows before 1.3.1 stored its contextLocation with backslashes (e.g. "..\\..\\AppContext.js"), which Linux treats as literal filename characters — so the CLI failed before running any migration. Upgrade to masterrecord@1.3.1: the CLI now normalizes path separators when reading and writing snapshots, so already-committed snapshots work without regeneration.
“Bulk insert failed, falling back to individual inserts” in your logs#
On versions before 1.3.1, saving a batch where rows populated different column sets (some rows leave optional fields unset) produced a malformed multi-row INSERT on MySQL/Postgres and silently fell back to slow per-row inserts. Upgrade to masterrecord@1.3.1 — heterogeneous batches now emit one statement per column signature and stay on the fast path, and omitted columns keep their database DEFAULT.
“masterrecord: table ‘X’ does not exist”#
The entity is registered but its table was never created — MasterRecord detects the engine’s missing-table error (SQLite no such table, MySQL ER_NO_SUCH_TABLE, Postgres 42P01) and fails loudly instead of silently returning nothing. Generate and run a migration:
masterrecord add-migration AddX AppContext && masterrecord update-database AppContext
# or, in a Master app
master db new AddX && master db migrate“No environment specified. Set the ‘master’ or ‘NODE_ENV’ environment variable”#
The context picks config/environments/env.<env>.json from NODE_ENV (or master). Set it for the process or the CLI run — master db … --env production sets it for you, and the scaffolded server.js defaults it to development:
NODE_ENV=development npx masterrecord update-database AppContext“Cannot read or find Context snapshot ‘appcontext_contextSnapShot.json’”#
add-migration / update-database need the snapshot that enable-migrations creates (EF creates it implicitly). Run it once — master db does this automatically when no snapshot exists:
masterrecord enable-migrations AppContextMigrations work on my machine but fail on a fresh database#
The symptom is an ALTER TABLE or a foreign key against a table that no migration ever creates: everything applies against the database you developed on, and update-databaseon an empty one stops at “no such table”. The cause is almost always schema created outside migrations — a bootstrap script, a hand-run CREATE TABLE, a restored dump.
Before 1.30.0 the snapshot was rewritten when migrations were applied, so that outside schema was recorded as though a migration had created it, and the next add-migration generated a delta on top of tables no migration builds. From 1.30.0 the snapshot is written only when a migration is authored — as in EF Core, where migrations add regenerates ModelSnapshot and database update never touches it — so this can no longer happen silently.
To repair a project already in this state, bring the outside schema under migrations:
# 1. author a migration that creates the missing tables
masterrecord add-migration CatchUpBaseTables AppContext
# 2. tell the databases that already HAVE that schema it is applied,
# without running it (EF: 'migrations script --idempotent' + history insert)
masterrecord baseline AppContext --all
# 3. verify the real invariant: every migration replays onto nothing
masterrecord update-database AppContext # against a throwaway empty databaseThen delete the bootstrap script. The rule to hold onto: if a table is not created by a migration, no database can be rebuilt from scratch — so make the fresh-database replay part of CI.
Writes vanish intermittently (save resolves, row unchanged)#
Almost always a context shared across requests — a module-level export default new AppContext()imported by every handler. A context is a unit of work; concurrent requests on one instance mix change sets and, on versions before 1.5.12, could silently drop another request’s write. Upgrade, and scope the context per request: master.addScoped('db', AppContext) → this.db, or master.useScope() / new AppContext() + close() outside requests. Also check that every saveChanges() / save() is awaited and that the query was not asNoTracking() (no-tracking entities are detached — their edits are never saved). See Change Tracking & Context Lifetime.
“ConcurrencyError … MR_CONCURRENCY_CONFLICT”#
Not a bug — an UPDATE/DELETE affected 0 rows because the row was modified (token mismatch) or deleted by someone else since you loaded it. reload() the entities in err.entries, re-apply your changes and save again. See Transactions & Concurrency.
“Query argument error … expected N value(s) for parameter placeholders”#
The number of $$ placeholders in the lambda must equal the number of extra arguments. A common cause is passing a direction to orderBy() — use orderByDescending((p) => p.created_at) instead of orderBy((p) => p.created_at, 'desc').
Booleans read back as 1 / 0#
On SQLite and MySQL, versions before 1.22.1 returned the stored integer. Upgrade — db.boolean() columns now materialize as true/false on every read path.
Still stuck?#
LOG_SQL=true to print the exact SQL MasterRecord runs — invaluable for diagnosing query and migration issues. Open an issue with that output on the MasterRecord repo.