can1357/oh-my-pi · error · RangeError
Delta table ${String(table)} is not in the allowlist
Error message
Delta table ${String(table)} is not in the allowlist What it means
Delta sync table names are restricted to an explicit allowlist (ALLOWED_DELTA_TABLES). assertDeltaTable validates any user-supplied table name and throws a RangeError for anything not in that set, preventing SQL injection and checkpoint/delta corruption from arbitrary table names.
Source
Thrown at packages/mnemopi/src/core/streaming.ts:288
static fromJSON(text: string): SyncCheckpoint {
return new SyncCheckpoint(JSON.parse(text) as SyncCheckpointInit);
}
}
type MemoryHost = {
readonly conn?: Database;
readonly db?: Database;
readonly dbPath?: string;
readonly db_path?: string;
};
function databaseOf(host: MemoryHost): Database {
const db = host.conn ?? host.db;
if (db === undefined) throw new TypeError("DeltaSync requires a memory object with conn or db");
return db;
}
function assertDeltaTable(table: unknown): asserts table is DeltaTable {
if (typeof table !== "string" || !ALLOWED_DELTA_TABLES.has(table as DeltaTable))
throw new RangeError(`Delta table ${String(table)} is not in the allowlist`);
}
function checkpointRoot(host: MemoryHost): string {
const path = host.dbPath ?? host.db_path;
return path === undefined || path === ":memory:"
? join(process.cwd(), ".mnemopi-sync")
: join(path, "..", "sync_checkpoints");
}
export class DeltaSync {
readonly checkpointDir: string;
private readonly db: Database;
constructor(
readonly mnemopi: MemoryHost,
checkpointDir?: string,
) {
this.db = databaseOf(mnemopi);
this.checkpointDir = checkpointDir ?? checkpointRoot(mnemopi);
mkdirSync(this.checkpointDir, { recursive: true });View on GitHub (pinned to 9690622007)
Solutions
- Use one of the exact allowlisted table-name string literals (import the DeltaTable type if available)
- Log/inspect ALLOWED_DELTA_TABLES to see the valid names and correct the call site
- If a new table is genuinely needed, add it to the allowlist in streaming.ts rather than bypassing the check
Example fix
// before
sync.computeDelta("main.memories" as string);
// after
sync.computeDelta("memories"); // exact allowlisted name Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = ["memories", /* ... other allowlisted names */];
function assertTable(table) {
if (typeof table !== "string" || !ALLOWED.includes(table)) throw new RangeError(`table ${table} not allowlisted`);
} Type guard
function isDeltaTable(table) {
return typeof table === "string" && ALLOWED_DELTA_TABLES.has(table);
} Try / catch
try {
sync.computeDelta(table);
} catch (err) {
if (err instanceof RangeError && err.message.includes("allowlist")) {
logger.warn("rejecting non-allowlisted delta table", { table });
return null;
}
throw err;
} Prevention
- Use only string literals from the DeltaTable union type
- Never build table names from user input or string concatenation
- Keep table names lowercase and exact; avoid schema-qualified names
- Update the allowlist (not call sites) when a new table is truly needed
When it happens
Trigger: Calling getCheckpoint, saveCheckpoint, setCheckpoint, computeDelta, or applyDelta with a table argument that is not a string or is not one of the allowlisted DeltaTable names; typos in the table name (e.g. "memmories"); dynamically built table names with suffixes or prefixes.
Common situations: Building the table name from user input or env config; schema renames after a migration; concatenating prefixes like "tmp_" or schema qualifiers like "main.memories"; passing a table name with different casing than the allowlist.
Related errors
- Unsupported vault:// file op: ${rawOp}
- Unsupported vault:// vault op: ${rawOp}
- SqlSessionStorage: unable to infer adapter from client.optio
- SqlSessionStorage: table name must match ${IDENT_RE.source}
- Invalid SQL identifier: ${name}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/115f105ae983394b.
Report an issue: GitHub.