agalwood/Motrix · critical · StaleSchemaError
new_tables_missing
new_tables_missing
Error message
The versioned database schema is incompatible with this build: expected tables `tasks`/`task_instances` are missing. This unpublished build updates the canonical v1 schema directly, so an existing local development database can have a valid version marker while its substantive tables are stale.
Action: delete the database file and restart the app to recreate it on the current v1 schema.
rm '${dbPath}' What it means
StaleSchemaError reason 'new_tables_missing', thrown by Guard B at line 345 when the 'tasks' OR 'task_instances' table is absent despite schema_version >= 1. A half-recovered or partially-migrated DB has a version marker but is missing the core Plan A tables; running v2+ migrations on top would fail cryptically.
Source
Thrown at src/core/session/migrations/index.ts:346
)
.get() !== undefined
const hasTransferSchema =
db
.prepare(
"SELECT 1 FROM sqlite_master WHERE type='table' AND name='transfer_totals'"
)
.get() !== undefined &&
db
.prepare(
"SELECT 1 FROM sqlite_master WHERE type='table' AND name='transfer_buckets'"
)
.get() !== undefined
const dbPath = (db as unknown as { name: string }).name
if (hasLegacySchema) {
throw new StaleSchemaError('legacy_table_present', dbPath)
}
if (!hasNewSchema) {
throw new StaleSchemaError('new_tables_missing', dbPath)
}
const taskColumns = new Set(
(
db.prepare('PRAGMA table_info(tasks)').all() as Array<{ name: string }>
).map((column) => column.name)
)
if (
!taskColumns.has('task_type') ||
!taskColumns.has('finished_at') ||
!taskColumns.has('error_message') ||
!taskColumns.has('error_code') ||
!taskColumns.has('error_detail_key') ||
!taskColumns.has('error_detail_params') ||
!taskColumns.has('diagnosis_revision')
) {
throw new StaleSchemaError('canonical_task_columns_missing', dbPath)
}
if (!hasTransferSchema) {View on GitHub (pinned to 1a708ee577)
Solutions
- Delete the DB and restart — migrate() recreates v1 including tasks/task_instances.
- If you suspect an interrupted migration, do not try to resume manually; reset and let migrate() run end-to-end.
- Verify the DB file is on a reliable filesystem and not being truncated by sync issues.
Example fix
# before: schema_version=1 but tasks/task_instances missing
# after
rm '${dbPath}'
# restart; migrate() runs v1 cleanly and creates both tables Defensive patterns
Strategy: try-catch
Type guard
function isStaleSchemaError(e: unknown): e is StaleSchemaError { return e instanceof StaleSchemaError; } Try / catch
try {
migrate(db);
} catch (e) {
if (e instanceof StaleSchemaError && e.reason === 'new_tables_missing') {
// tasks/task_instances missing — reset DB; investigate interrupted migration if recurring
} else throw e;
} Prevention
- Treat migrate() as atomic — never kill the process mid-migration.
- Use a reliable local filesystem; do not store the DB on a network share subject to truncation.
- In tests, build schema from scratch via migrate() rather than from fixtures.
When it happens
Trigger: migrate() Guard B computes hasNewSchema (tasks AND task_instances both present); if false, throws at line 346. Note: this check is specifically for tasks/task_instances; task_files is checked separately at line 367 (also new_tables_missing).
Common situations: A failed/interrupted v1 migration that wrote schema_version=1 but crashed before creating tasks/task_instances; a partially-restored DB backup; manual deletion of just the tasks tables while leaving schema_version.
Related errors
- canonical_task_columns_missing
- inherited_schema_missing
- inspector_activity_schema_missing
- foreign_key_violation
- legacy_table_present
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/afd03c4dfb6145f0.
Report an issue: GitHub.