{"record":{"id":"afd03c4dfb6145f0","repo":"agalwood/Motrix","slug":"new-tables-missing","errorCode":"new_tables_missing","errorMessage":"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.\n\nAction: delete the database file and restart the app to recreate it on the current v1 schema.\n  rm '${dbPath}'","messagePattern":"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\\.\n\nAction: delete the database file and restart the app to recreate it on the current v1 schema\\.\n  rm '(.+?)'","errorType":"exception","errorClass":"StaleSchemaError","httpStatus":null,"severity":"critical","filePath":"src/core/session/migrations/index.ts","lineNumber":346,"sourceCode":"        )\n        .get() !== undefined\n    const hasTransferSchema =\n      db\n        .prepare(\n          \"SELECT 1 FROM sqlite_master WHERE type='table' AND name='transfer_totals'\"\n        )\n        .get() !== undefined &&\n      db\n        .prepare(\n          \"SELECT 1 FROM sqlite_master WHERE type='table' AND name='transfer_buckets'\"\n        )\n        .get() !== undefined\n    const dbPath = (db as unknown as { name: string }).name\n    if (hasLegacySchema) {\n      throw new StaleSchemaError('legacy_table_present', dbPath)\n    }\n    if (!hasNewSchema) {\n      throw new StaleSchemaError('new_tables_missing', dbPath)\n    }\n    const taskColumns = new Set(\n      (\n        db.prepare('PRAGMA table_info(tasks)').all() as Array<{ name: string }>\n      ).map((column) => column.name)\n    )\n    if (\n      !taskColumns.has('task_type') ||\n      !taskColumns.has('finished_at') ||\n      !taskColumns.has('error_message') ||\n      !taskColumns.has('error_code') ||\n      !taskColumns.has('error_detail_key') ||\n      !taskColumns.has('error_detail_params') ||\n      !taskColumns.has('diagnosis_revision')\n    ) {\n      throw new StaleSchemaError('canonical_task_columns_missing', dbPath)\n    }\n    if (!hasTransferSchema) {","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/session/migrations/index.ts#L328-L364","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"# before: schema_version=1 but tasks/task_instances missing\n# after\n  rm '${dbPath}'\n# restart; migrate() runs v1 cleanly and creates both tables","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isStaleSchemaError(e: unknown): e is StaleSchemaError { return e instanceof StaleSchemaError; }","tryCatchPattern":"try {\n  migrate(db);\n} catch (e) {\n  if (e instanceof StaleSchemaError && e.reason === 'new_tables_missing') {\n    // tasks/task_instances missing — reset DB; investigate interrupted migration if recurring\n  } else throw e;\n}","preventionTips":["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."],"tags":["database","sqlite","migration","tasks","stale-schema","partial-migration"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}