{"record":{"id":"6e9f475fab6c4989","repo":"can1357/oh-my-pi","slug":"sqlite-selectors-must-include-a-table-name","errorCode":null,"errorMessage":"SQLite selectors must include a table name","messagePattern":"SQLite selectors must include a table name","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/sqlite-reader.ts","lineNumber":588,"sourceCode":"\t\t}\n\t\tif (!rawQuery.trim()) {\n\t\t\tthrow new ToolError(\"SQLite query parameter 'q' cannot be empty\");\n\t\t}\n\t\treturn { kind: \"raw\", sql: rawQuery };\n\t}\n\n\tif (!normalizedSubPath) {\n\t\tif (params.size > 0) {\n\t\t\tthrow new ToolError(\"SQLite query parameters require a table selector or q=SELECT...\");\n\t\t}\n\t\treturn { kind: \"list\" };\n\t}\n\n\tconst separatorIndex = normalizedSubPath.indexOf(\":\");\n\tconst table = separatorIndex === -1 ? normalizedSubPath : normalizedSubPath.slice(0, separatorIndex);\n\tconst key = separatorIndex === -1 ? undefined : normalizedSubPath.slice(separatorIndex + 1);\n\tif (!table) {\n\t\tthrow new ToolError(\"SQLite selectors must include a table name\");\n\t}\n\n\tif (key !== undefined && key.length > 0) {\n\t\tif (params.size > 0) {\n\t\t\tthrow new ToolError(\"SQLite row lookups cannot be combined with query parameters\");\n\t\t}\n\t\treturn { kind: \"row\", table, key };\n\t}\n\n\tconst where = validateWhereClause(params.get(\"where\") ?? undefined);\n\tconst order = params.get(\"order\")?.trim() || undefined;\n\tconst hasQueryParams = params.has(\"limit\") || params.has(\"offset\") || order !== undefined || where !== undefined;\n\tif (hasQueryParams) {\n\t\tconst knownKeys = new Set([\"limit\", \"offset\", \"order\", \"where\"]);\n\t\tfor (const keyName of params.keys()) {\n\t\t\tif (!knownKeys.has(keyName)) {\n\t\t\t\tthrow new ToolError(`Unsupported SQLite query parameter '${keyName}'`);\n\t\t\t}","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/sqlite-reader.ts#L570-L606","documentation":"Thrown when the table selector resolves to an empty table name — typically a sub-path like 'db.sqlite/:key' or ':123' where nothing precedes the ':' separator. The parser requires a table name before the colon.","triggerScenarios":"Sub-path ':id' or '/:rowid' where the table was omitted; empty table variable interpolated into the path; malformed selector with a leading colon.","commonSituations":"Template strings with an unset table variable; confusing the tool's 'table:key' syntax with ':param' route syntax from web frameworks.","solutions":["Include the table name before the colon: 'users:42'","Fix the empty/unset table variable in the URL builder","If you meant a row lookup, format is table:key, not :key"],"exampleFix":"// before\ndb.sqlite/:42\n// after\ndb.sqlite/users:42","handlingStrategy":"validation","validationCode":"const m = subPath.match(/^([^:]+)(?::(.*))?$/);\nif (!m || !m[1]) throw new Error('selector must be table or table:key');","typeGuard":null,"tryCatchPattern":"try {\n  await reader.read(`db.sqlite/${subPath}`);\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes('must include a table name')) {\n    // fix the selector format — table name must precede ':'\n  } else throw err;\n}","preventionTips":["Remember the selector syntax is table:key, not :key","Interpolate-checked table names into path templates","Add a regex validation on the sub-path before the call"],"tags":["sqlite","validation","selector-format","api-misuse"],"backgroundTag":"missing-required-parameter","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}