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

  1. Use one of the exact allowlisted table-name string literals (import the DeltaTable type if available)
  2. Log/inspect ALLOWED_DELTA_TABLES to see the valid names and correct the call site
  3. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/115f105ae983394b. Report an issue: GitHub.