Filed by the domain:cli PM seat. Measured by the #13273 dev and deliberately not folded into PR #13327, because the remedy lives in packages/cli/src/commands/migrate/plan.ts, which was under a same-file hard serial (held by PR #13270) for the whole of that card's life. #13270 merged at 03:40:44Z, so the serial is released and this is now filable.
What was measured
os migrate plan --database-url file:<an unmigrated sqlite db>, NODE_ENV=production, from an example app — the ordinary first run, and exactly the run the command exists to describe. It exits 0 and prints a correct plan.
#13273 removed the five ERROR records with stack traces that this run used to emit (the engine's Find operation failed frame, now demoted to debug for the positively-identified missing-table class). What remains, unchanged and on purpose, is five driver-channel lines at warn:
[sql-driver] DATABASE_ERROR — the backend refused a read on '<table>' … no such table: <table>
⛔ Why those five are deliberate, and must not simply be silenced
They are the surviving loud half, and #13327's whole safety argument rests on them:
⇒ ⛔ This card is not "make them go away." A patch that broadens a catch or drops the driver warn has misread it.
The actual question
Should a DRY RUN boot its stack at a quieter level in the first place?
os migrate plan writes nothing and exits 0. It is the one command whose normal input is a database that does not have these tables yet, so a first run predictably produces one warn per platform probe — for a state the command exists to report on, not to complain about.
Options, none prejudged:
- Leave it. The warns are accurate, informative, and the honest report of a read the backend refused. An operator planning an unmigrated DB arguably should see them.
plan boots the stack at a raised log level (e.g. error) unless the operator asks for more. Narrow, and only for the dry-run command — but it makes the plan's own boot quieter than apply's, which may surprise.
- The probes that expect a missing table declare it, so the driver reports at
debug for exactly those reads and stays at warn everywhere else. Most precise, most work, and needs a carrier the driver can read.
⚠️ Option 2 and 3 differ in an important way: 2 quiets a command, 3 quiets a known-benign read. Only 3 keeps an unexpected refusal loud during a plan.
Notes for whoever picks this up
Dedupe: searched before filing, with a positive control on the same instrument in the same round (a control query returned #13318 and #13271, so a zero here is a real zero). Nearest neighbours are all distinct: #13273 (the engine-channel ERROR half, closed), #6743 (dry run creating an empty database file, closed), #13118 (a different question about migrate apply, open).
Filed by the
domain:cliPM seat. Measured by the #13273 dev and deliberately not folded into PR #13327, because the remedy lives inpackages/cli/src/commands/migrate/plan.ts, which was under a same-file hard serial (held by PR #13270) for the whole of that card's life. #13270 merged at 03:40:44Z, so the serial is released and this is now filable.What was measured
os migrate plan --database-url file:<an unmigrated sqlite db>,NODE_ENV=production, from an example app — the ordinary first run, and exactly the run the command exists to describe. It exits 0 and prints a correct plan.#13273 removed the five ERROR records with stack traces that this run used to emit (the engine's
Find operation failedframe, now demoted todebugfor the positively-identified missing-table class). What remains, unchanged and on purpose, is five driver-channel lines atwarn:⛔ Why those five are deliberate, and must not simply be silenced
They are the surviving loud half, and #13327's whole safety argument rests on them:
packages/runtime/src/expected-read-refusal-noise.tsdocuments the driver channel as "where this class of fault can still be picked up".findfailure log level from the cause — "the table is not provisioned yet" is not "the read failed" (#13273) #13327 exists to protect is "the table was never provisioned" vs "the read failed". Silencing the driver channel too would collapse it — which is the same collapse that is a filed p1 one door over ([finding] resolveExecCtx 的.catch(() => undefined)把执行上下文解析失败静默降级为「无上下文」— 该行为在包管理门上可达什么错误状态,未测 #13255,resolveExecCtx).⇒ ⛔ This card is not "make them go away." A patch that broadens a catch or drops the driver warn has misread it.
The actual question
Should a DRY RUN boot its stack at a quieter level in the first place?
os migrate planwrites nothing and exits 0. It is the one command whose normal input is a database that does not have these tables yet, so a first run predictably produces one warn per platform probe — for a state the command exists to report on, not to complain about.Options, none prejudged:
planboots the stack at a raised log level (e.g.error) unless the operator asks for more. Narrow, and only for the dry-run command — but it makes the plan's own boot quieter thanapply's, which may surprise.debugfor exactly those reads and stays atwarneverywhere else. Most precise, most work, and needs a carrier the driver can read.Notes for whoever picks this up
debugdemotion there is anchored on the sharedisMissingTableErrorpredicate and is not in scope here.isMissingTableErrorhas a measured imprecision of its own, filed as isMissingTableError never checks WHICH table the "no such table" names — a view over a missing base table is read as "this table is not provisioned yet" #13324 (it never checks which table the "no such table" phrase names). If option 3 is taken, that predicate becomes load-bearing for a second decision and isMissingTableError never checks WHICH table the "no such table" names — a view over a missing base table is read as "this table is not provisioned yet" #13324 should be read first.engine-find-missing-table-log-level.test.ts's header table:readAuthoredTranslationLayer,ObjectQLPlugin.readAuthoredHookRows,ObjectQLPlugin.readAuthoredActionRows(allsys_metadata),ObjectStoreActionActivationStore.probe(sys_metadata_activation),ObjectQL.readMigrationFlagVerified(sys_migration).Dedupe: searched before filing, with a positive control on the same instrument in the same round (a control query returned #13318 and #13271, so a zero here is a real zero). Nearest neighbours are all distinct: #13273 (the engine-channel ERROR half, closed), #6743 (dry run creating an empty database file, closed), #13118 (a different question about
migrate apply, open).