{"record":{"id":"fc3f3afb8c4de664","repo":"can1357/oh-my-pi","slug":"error-instanceof-error-error-message-string-er-fc3f3a","errorCode":null,"errorMessage":"error instanceof Error ? error.message : String(error) (wraps underlying error)","messagePattern":"error instanceof Error \\? error\\.message : String\\(error\\) \\(wraps underlying error\\)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/read-sqlite.ts","lineNumber":211,"sourceCode":"\t\t\t\t\ttable: \"query\",\n\t\t\t\t\tdbPath: resolvedSqlitePath.absolutePath,\n\t\t\t\t});\n\t\t\t\tif (result.truncated) {\n\t\t\t\t\toutput += `\\n[Output capped at ${MAX_RAW_QUERY_ROWS} rows; add a LIMIT/OFFSET clause to the query to page through more]`;\n\t\t\t\t}\n\t\t\t\treturn toolResult<ReadToolDetails>(details)\n\t\t\t\t\t.text(prependSuffixResolutionNotice(output, resolvedSqlitePath.suffixResolution))\n\t\t\t\t\t.sourcePath(resolvedSqlitePath.absolutePath)\n\t\t\t\t\t.done();\n\t\t\t}\n\t\t}\n\n\t\tthrow new ToolError(\"Unsupported SQLite selector\");\n\t} catch (error) {\n\t\tif (error instanceof ToolError) {\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new ToolError(error instanceof Error ? error.message : String(error));\n\t} finally {\n\t\tdb?.close();\n\t}\n}\n","sourceCodeStart":193,"sourceCodeEnd":216,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/read-sqlite.ts#L193-L216","documentation":"readSqlite wraps any non-ToolError thrown inside the read (SQLite driver errors, malformed DB files, SQL failures in raw queries) into a ToolError whose message is error.message (or String(error)). The original stack/type is discarded, so callers only see the flattened message string.","triggerScenarios":"executeReadQuery on invalid SQL in a :raw selector; queryRows/getTableSchema hitting a corrupt or encrypted (non-SQLite) file; native sqlite driver throwing (disk I/O, locked DB); any bug in helper functions inside the try block.","commonSituations":"Passing a text file, WAL-only remnants, or an encrypted SQLCipher database where SQLite header magic fails; writing SELECT with a typo in :raw mode; database locked by another writer.","solutions":["Read the wrapped message — it usually names the SQLite failure (e.g. 'file is not a database', 'no such table').","Verify the file is a real SQLite DB (magic header 'SQLite format 3\\u0000').","Fix the SQL in :raw selectors (check table/column names via :schema first).","Close other connections holding a write lock; retry if it was transient 'database is locked'.","If the stack trace matters, run outside the tool wrapper (e.g. sqlite3 CLI) to see full details."],"exampleFix":"// before: raw unvetted SQL\nfile.db:raw?sql=SELEC * FROM users\n// after: validated SQL and correct names\nfile.db:raw?sql=SELECT * FROM users LIMIT 20","handlingStrategy":"try-catch","validationCode":"import { $ } from 'bun';\n// verify it is a SQLite database before reading\nconst header = Buffer.from(await Bun.file(dbPath).slice(0, 16).arrayBuffer());\nif (!header.toString('latin1').startsWith('SQLite format 3')) {\n  throw new Error(`${dbPath} is not a SQLite database`);\n}","typeGuard":"function isSqliteFile(header: Uint8Array): boolean {\n  return Array.from(header.slice(0, 16)).join(',') ===\n    Array.from(Buffer.from('SQLite format 3\\u0000', 'latin1')).join(',');\n}","tryCatchPattern":"try {\n  return await readSqlite(dbPath, selector);\n} catch (e) {\n  if (e instanceof ToolError) {\n    // message is the flattened sqlite driver error\n    if (/file is not a database/i.test(e.message)) { /* wrong file type */ }\n    if (/database is locked/i.test(e.message)) { /* retry after releasing writer */ }\n  }\n  throw e;\n}","preventionTips":["Check the 16-byte SQLite magic header before opening unknown files.","Run read-only queries; keep other writers from holding locks during reads.","Validate :raw SQL table/column names via the :schema selector first.","Decrypt/convert SQLCipher or WAL-orphaned files before tool reads."],"tags":["sqlite","error-wrapping","sql"],"backgroundTag":"sqlite-query-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}