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
- Pass a positive integer (1..500) as limit, or omit it to use the default (20).
- Sanitize the value before building the selector: Number.parseInt and check Number.isInteger(n) && n >= 1.
- 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
- Only interpolate sanitized integers into selector query strings.
- Remember limit starts at 1, not 0.
- Rely on the built-in clamp of 500 instead of passing oversized values.
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
- SQLite offset must be a non-negative integer; got '${value}'
- ${label} must be an integer; got '${key}'
- symbol is required for project-aware ${action}; pass symbol=
- Symbol "${symbol}" occurrence ${occurrence} is out of bounds
- Report cannot be empty.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/70ac96c2761d7171.
Report an issue: GitHub.