can1357/oh-my-pi · error · ToolError

SQLite offset must be a non-negative integer; got '${value}'

Error message

SQLite offset must be a non-negative integer; got '${value}'

What it means

parseOffset validates the `offset` query parameter of SQLite selector URLs. It throws this ToolError when offset is present, non-empty, and not a parseable integer >= 0 (e.g. '-1', 'ten', '1.5'). Empty/null offset defaults to 0.

Source

Thrown at packages/coding-agent/src/tools/sqlite-reader.ts:312

	if (value === null || value.trim().length === 0) {
		return fallback;
	}

	const parsed = Number.parseInt(value, 10);
	if (!Number.isFinite(parsed) || parsed < 1) {
		throw new ToolError(`SQLite limit must be a positive integer; got '${value}'`);
	}
	return Math.min(parsed, MAX_QUERY_LIMIT);
}

function parseOffset(value: string | null): number {
	if (value === null || value.trim().length === 0) {
		return 0;
	}

	const parsed = Number.parseInt(value, 10);
	if (!Number.isFinite(parsed) || parsed < 0) {
		throw new ToolError(`SQLite offset must be a non-negative integer; got '${value}'`);
	}
	return parsed;
}

function getTableMasterRow(db: Database, table: string): SqliteMasterRow {
	const row =
		db
			.prepare<SqliteMasterRow, [string]>(
				"SELECT name, sql FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' AND name = ?",
			)
			.get(table) ?? null;
	if (!row) {
		throw new ToolError(`SQLite table '${table}' not found`);
	}
	return row;
}

function getTableInfoRows(db: Database, table: string): SqliteTableInfoRow[] {

View on GitHub (pinned to 9690622007)

Solutions

  1. Pass a non-negative integer offset (0 or greater), or omit it to start at 0.
  2. Guard pagination math: Math.max(0, (page - 1) * size) with Number.isFinite checks.
  3. Validate numeric query params before interpolating them into the selector string.

Example fix

// before
const url = `db.sqlite?table=logs&offset=${(page - 1) * size}`; // page undefined -> NaN
// after
const offset = Math.max(0, ((Number(page) || 1) - 1) * size);
const url = `db.sqlite?table=logs&offset=${offset}`;
Defensive patterns

Strategy: validation

Validate before calling

function safeOffset(v: string | null | undefined): string {
  if (v == null || v.trim() === "") return "0";
  const n = Number.parseInt(v, 10);
  if (!Number.isInteger(n) || n < 0) throw new Error(`bad offset: ${v}`);
  return String(n);
}

Type guard

function isNonNegativeIntString(v: string): boolean { return /^\d+$/.test(v.trim()); }

Try / catch

try { return await readSelector(url); } catch (e) { if (e instanceof ToolError && e.message.startsWith("SQLite offset must be")) { return readSelector(setQueryParam(url, "offset", "0")); } throw e; }

Prevention

When it happens

Trigger: A selector with offset=-1, a float like '2.5', or non-numeric text such as 'end'; arithmetic producing NaN stringified into the URL (e.g. `${page * size}` with undefined page).

Common situations: Pagination math with undefined page variables; negative page indexes from zero-based pagination wrap-around; hand-written offsets with typos.

Understand the failure class

Background: "must be positive", "Invalid value": how libraries reject invalid parameter values (ValueError, ArgumentError, INVALID_PARAMETER_VALUE) — this error's family across 28 libraries.

Related errors


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