thedotmack/claude-mem · critical
schema v46: . row is not a positive canonical uint64…
Error message
schema v46: ${target.table}.${target.column} row ${row.row_id} is not a positive canonical uint64 revision What it means
The v46 migration validates every revision value with assertCanonicalDecimal(..., { positive: true }) — it must be a positive canonical decimal uint64 (no leading zeros, no signs). A value failing this check means the revision column holds invalid data, so the migration aborts.
Solutions
- Locate bad rows: SELECT CAST(id AS TEXT), sync_rev FROM <table> WHERE typeof(sync_rev)='text' AND (sync_rev GLOB '*[^0-9]*' OR sync_rev GLOB '0*' OR sync_rev = '')
- Correct the revision to the expected positive canonical decimal string
- Restore a backup taken before migration
- Report as a bug including the offending value
Example fix
// before (invalid) sync_rev = '007' // after sync_rev = '7'
Defensive patterns
Strategy: validation
Validate before calling
function isCanonicalUint64(v: string) {
return /^[1-9][0-9]*$/.test(v) && BigInt(v) <= 18446744073709551615n;
}
const bad = db.query("SELECT sync_rev FROM sdk_sessions WHERE typeof(sync_rev)='text'").all()
.filter(r => !isCanonicalUint64(r.sync_rev)); Try / catch
try { store = new SessionStore(dbPath); } catch (e) {
if (String(e.message).includes('not a positive canonical uint64')) {
fixOrRestoreRevisionRows(dbPath);
} else throw e;
} Prevention
- Never write 0, negative, zero-padded, or non-numeric values into revision columns
- Use the library's revision-assignment APIs
- Back up before migrating
When it happens
Trigger: A row whose CAST(column AS TEXT) revision is e.g. '0', '-5', '007', 'abc', or exceeds uint64 range when ensureSyncRevisionTextAffinity streams rows.
Common situations: Rows written by an older buggy version; manual edits setting sync_rev to 0 or a negative number; values produced by float rounding then stored as text.
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 has unsupported storage
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/9ba679c8845eba48.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/sqlite/SessionStore.ts:730
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(
`ALTER TABLE ${target.table} ADD COLUMN ${target.temporary} TEXT NOT NULL DEFAULT '1'`
);
this.db.run(
`UPDATE ${target.table} SET ${target.temporary} = CAST(${target.column} AS TEXT)`
);
const mismatch = this.db.prepare(`
SELECT CAST(id AS TEXT) AS row_idView on GitHub (pinned to d8bc9755e7)