thedotmack/claude-mem · critical
schema v46: . row has unsupported storage
Error message
schema v46: ${target.table}.${target.column} row ${row.row_id} has unsupported ${row.storage_type} storage What it means
During the v46 revision-affinity migration, a row's sync-revision column has a SQLite storage type other than integer or text (e.g. 'real' is handled separately, so this catches blob/null-adjacent or other odd storage). The migration only knows how to normalize integer and text values, so it fails fast.
Solutions
- Find the offending row with: SELECT CAST(id AS TEXT), typeof(sync_rev) FROM <table> WHERE typeof(sync_rev) NOT IN ('integer','text','real')
- Fix or delete the malformed row, then restart
- Restore a pre-migration backup
- Report as a bug with the row's storage type
Example fix
-- inspect and repair a BLOB-stored revision UPDATE sdk_sessions SET sync_rev = CAST(sync_rev AS TEXT) WHERE typeof(sync_rev) = 'blob';
Defensive patterns
Strategy: try-catch
Validate before calling
const bad = db.query("SELECT COUNT(*) c FROM sdk_sessions WHERE typeof(sync_rev) NOT IN ('integer','text','real')").get();
if (bad.c > 0) console.error('BLOB/other storage in revision column; repair before upgrade'); Try / catch
try { store = new SessionStore(dbPath); } catch (e) {
if (String(e.message).includes('unsupported') && String(e.message).startsWith('schema v46')) {
repairOrRestore(dbPath);
} else throw e;
} Prevention
- Only access the DB through the library's own writers
- Audit ad-hoc tooling that inserts into sync-revision columns
- Back up before schema-changing upgrades
When it happens
Trigger: Streaming rows in ensureSyncRevisionTextAffinity encounters typeof(column) not in ('integer','text','real') — e.g. a BLOB-stored revision.
Common situations: External tooling or a different driver inserted a BLOB into the revision column; database corruption from a crashed non-SQLite writer.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Column not found in , skipping rename
- schema v46: failed to copy
- schema v46: missing .
- schema v46: . row is REAL and unrecoverably rounded
- schema v46: . row is not a positive canonical uint64…
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/06564fb64f5a4ded.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/sqlite/SessionStore.ts:723
const source = columns.find(info => info.name === target.column);
if (!source) {
throw new Error(`schema v46: missing ${target.table}.${target.column}`);
}
for (const raw of streamRows(this.db.query(`
SELECT CAST(id AS TEXT) AS row_id,
typeof(${target.column}) AS storage_type,
CAST(${target.column} AS TEXT) AS revision
FROM ${target.table}
`))) {
const row = raw as { row_id: string; storage_type: string; revision: string | null };
if (row.storage_type === 'real') {
throw new Error(
`schema v46: ${target.table}.${target.column} row ${row.row_id} is REAL and unrecoverably rounded`
);
}
if (row.storage_type !== 'integer' && row.storage_type !== 'text') {
throw new Error(
`schema v46: ${target.table}.${target.column} row ${row.row_id} has unsupported ${row.storage_type} storage`
);
}
try {
assertCanonicalDecimal(row.revision, { positive: true });
} catch {
throw new Error(
`schema v46: ${target.table}.${target.column} row ${row.row_id} is not a positive canonical uint64 revision`
);
}
}
if (isText(source)) continue;
if (columns.some(info => info.name === target.temporary)) {
throw new Error(`schema v46: unexpected temporary column ${target.table}.${target.temporary}`);
}
this.db.run(View on GitHub (pinned to d8bc9755e7)