Found while working #13204; out of that card's scope, filed unassigned for triage.
Measured
Built CLI, os migrate plan against a sqlite database whose platform tables have
not been created yet — the ordinary state of a first run, and exactly the run the
command exists to describe. Fixture: an objectstack.config.ts composing
SecurityPlugin, a control DB carrying a handful of tables, no compiled artifact.
The command succeeds: exit 0, a correct plan (14 table(s) to create, 32 column(s) to add). On the way there it emits, at ERROR level, with full
stack traces:
4 x ERROR Find operation failed
2 x "object":"sys_metadata"
1 x "object":"sys_metadata_activation"
1 x "object":"sys_migration"
4 x [sql-driver] DATABASE_ERROR - the backend refused a read on '<name>' (SQLITE_ERROR) ... no such table
Call sites reached, from the stacks: announceOpenMigrationGates ->
readMigrationFlagVerified (sys_migration), ObjectStoreActionActivationStore.probe
(sys_metadata_activation), readAuthoredTranslationLayer and
ObjectQLPlugin.readAuthoredHookRows / readAuthoredActionRows (sys_metadata).
Why this looks like a defect rather than a true report
Each of those callers treats the failure as a normal, expected answer, and
says so in its own code:
engine.ts on the migration flag: "no sys_migration object registered, no
row, an unreadable table, a ... -> false"; it names an unreadable table as one
of the inputs its verdict is defined over.metadata-activation-store.probe already follows its ERROR with a WARN that
states the consequence in operator terms — so the ERROR beneath it adds a
stack trace and no information.- the authored-hook / authored-action re-syncs report
authoredRows: 0 and
carry on.
So the ERROR channel fires for a condition every consumer downstream of it
handles as routine. AGENTS.md already names this failure mode in
sql-driver.ts's own comment on a nearby line: "the over-application AGENTS.md
warns trains everyone to skim error". On os migrate plan the cost is
concrete: the first thing an operator sees when planning an unmigrated database
is four stack traces, in a command whose header documents it as a dry run that
writes nothing.
Not in scope of #13204, and not caused by it
The records come from @objectstack/objectql and @objectstack/core boot
paths, not from the migrate command. They are present on origin/main at
74049254 with no part of #13204 applied — this is a pre-existing shape that
#13204's fixture happened to put in front of a reader.
Open questions for triage
- Is the right fix at the READ site (a
find that tolerates a missing table
for these probe-shaped reads and returns "unknown" without logging ERROR), or
at the LOG site (demote to debug when the driver's own classification is
"relation does not exist")? - Does the same shape appear on
os serve first boot, where nobody is reading
for a dry-run verdict? Not measured here.
Reproduce
os migrate plan --database-url file:/path/to/an-unmigrated.db
in a project directory with an objectstack.config.ts, NODE_ENV=production.
Generated by Claude Code
Found while working #13204; out of that card's scope, filed unassigned for triage.
Measured
Built CLI,
os migrate planagainst a sqlite database whose platform tables havenot been created yet — the ordinary state of a first run, and exactly the run the
command exists to describe. Fixture: an
objectstack.config.tscomposingSecurityPlugin, a control DB carrying a handful of tables, no compiled artifact.The command succeeds: exit 0, a correct plan (
14 table(s) to create, 32 column(s) to add). On the way there it emits, at ERROR level, with fullstack traces:
Call sites reached, from the stacks:
announceOpenMigrationGates->readMigrationFlagVerified(sys_migration),ObjectStoreActionActivationStore.probe(
sys_metadata_activation),readAuthoredTranslationLayerandObjectQLPlugin.readAuthoredHookRows/readAuthoredActionRows(sys_metadata).Why this looks like a defect rather than a true report
Each of those callers treats the failure as a normal, expected answer, and
says so in its own code:
engine.tson the migration flag: "nosys_migrationobject registered, norow, an unreadable table, a ... -> false"; it names an unreadable table as one
of the inputs its verdict is defined over.
metadata-activation-store.probealready follows its ERROR with a WARN thatstates the consequence in operator terms — so the ERROR beneath it adds a
stack trace and no information.
authoredRows: 0andcarry on.
So the ERROR channel fires for a condition every consumer downstream of it
handles as routine. AGENTS.md already names this failure mode in
sql-driver.ts's own comment on a nearby line: "the over-application AGENTS.mdwarns trains everyone to skim
error". Onos migrate planthe cost isconcrete: the first thing an operator sees when planning an unmigrated database
is four stack traces, in a command whose header documents it as a dry run that
writes nothing.
Not in scope of #13204, and not caused by it
The records come from
@objectstack/objectqland@objectstack/corebootpaths, not from the migrate command. They are present on
origin/mainat74049254with no part of #13204 applied — this is a pre-existing shape that#13204's fixture happened to put in front of a reader.
Open questions for triage
findthat tolerates a missing tablefor these probe-shaped reads and returns "unknown" without logging ERROR), or
at the LOG site (demote to
debugwhen the driver's own classification is"relation does not exist")?
os servefirst boot, where nobody is readingfor a dry-run verdict? Not measured here.
Reproduce
in a project directory with an
objectstack.config.ts,NODE_ENV=production.Generated by Claude Code