can1357/oh-my-pi · error · ToolError

SQLite limit must be a positive integer; got '${value}'

Error message

SQLite limit must be a positive integer; got '${value}'

What it means

parseLimit validates the `limit` query parameter of SQLite selector URLs (e.g. db.sqlite?table=t&limit=10). It throws this ToolError when limit is present, non-empty, and not a parseable integer >= 1 (e.g. 'abc', '0', '-5', '1.5'). Values parse via Number.parseInt base 10, and valid values are clamped to MAX_QUERY_LIMIT (500).

Source

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

	for (const row of rows) {
		const cells = columns.map((column, index) =>
			padCell(stringifySqliteValue(row[column]), widths[index] ?? MIN_COLUMN_WIDTH),
		);
		lines.push(`| ${cells.join(" | ")} |`);
	}

	return lines.map(line => truncateToWidth(replaceTabs(line), MAX_RENDER_WIDTH)).join("\n");
}

function parseLimit(value: string | null, fallback: number): number {
	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 =

View on GitHub (pinned to 9690622007)

Solutions

  1. Pass a positive integer (1..500) as limit, or omit it to use the default (20).
  2. Sanitize the value before building the selector: Number.parseInt and check Number.isInteger(n) && n >= 1.
  3. Clamp large values yourself or rely on the built-in clamp to 500 — no need to cap manually.

Example fix

// before
const url = `data.sqlite?table=users&limit=${limit ?? 0}`;
// after
const n = Math.max(1, Math.floor(Number(limit) || 20));
const url = `data.sqlite?table=users&limit=${n}`;
Defensive patterns

Strategy: validation

Validate before calling

function safeLimit(v: string | null | undefined): string | undefined {
  if (v == null || v.trim() === "") return undefined;
  const n = Number.parseInt(v, 10);
  if (!Number.isInteger(n) || n < 1) throw new Error(`bad limit: ${v}`);
  return String(Math.min(n, 500));
}

Type guard

function isPositiveIntString(v: string): boolean { return /^\d+$/.test(v.trim()) && Number.parseInt(v, 10) >= 1; }

Try / catch

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

Prevention

When it happens

Trigger: A sqlite-reader selector with limit=0, a negative limit, a float, a non-numeric string, or a value with stray characters like '10px'; empty string is allowed and falls back.

Common situations: Programmatic URL building that stringifies 0 or NaN; copying limits with units from other tools; off-by-one assumptions that limit starts at 0; UI inputs passed through unvalidated.

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/70ac96c2761d7171. Report an issue: GitHub.