{"record":{"id":"743aaf5ae594815d","repo":"coleam00/Archon","slug":"corrupt-commands-json-for-codebase-id-unable-t","errorCode":null,"errorMessage":"Corrupt commands JSON for codebase ${id}: unable to parse stored data. Run UPDATE remote_agent_codebases SET commands = '{}' WHERE id = '${id}' to reset.","messagePattern":"Corrupt commands JSON for codebase (.+?): unable to parse stored data\\. Run UPDATE remote_agent_codebases SET commands = '(.+?)' WHERE id = '(.+?)' to reset\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/db/codebases.ts","lineNumber":78,"sourceCode":"    [JSON.stringify(commands), id]\n  );\n}\n\nexport async function getCodebaseCommands(\n  id: string\n): Promise<Record<string, { path: string; description: string }>> {\n  const result = await pool.query<{\n    commands: Record<string, { path: string; description: string }> | string;\n  }>('SELECT commands FROM remote_agent_codebases WHERE id = $1', [id]);\n  const raw = result.rows[0]?.commands;\n  // SQLite returns TEXT columns as strings; PostgreSQL JSONB returns objects\n  let parsed: Record<string, { path: string; description: string }>;\n  if (typeof raw === 'string') {\n    try {\n      parsed = JSON.parse(raw);\n    } catch (err) {\n      getLog().error({ codebaseId: id, raw, err }, 'db.codebase_commands_json_parse_failed');\n      throw new Error(\n        `Corrupt commands JSON for codebase ${id}: unable to parse stored data. ` +\n          `Run UPDATE remote_agent_codebases SET commands = '{}' WHERE id = '${id}' to reset.`\n      );\n    }\n  } else {\n    parsed = raw ?? {};\n  }\n  // Spread to ensure mutable copy - Bun's SQLite driver returns frozen objects\n  return { ...parsed };\n}\n\nexport async function registerCommand(\n  id: string,\n  name: string,\n  command: { path: string; description: string }\n): Promise<void> {\n  const commands = await getCodebaseCommands(id);\n  commands[name] = command;","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/core/src/db/codebases.ts#L60-L96","documentation":"getCodebaseCommands reads the `commands` column of remote_agent_codebases and, when it is stored as a string, parses it as JSON. If parsing fails the stored data is corrupt, so it throws with the codebase id and a literal SQL statement the operator can run to reset commands to '{}'. The library refuses to guess or silently swallow malformed persisted data.","triggerScenarios":"The commands column for the given codebase id contains a non-JSON string (hand-edited row, truncated write, legacy serialization) and JSON.parse throws.","commonSituations":"Manual UPDATE/INSERT with malformed JSON; a migration or older binary wrote a different format; a partially applied write from a crashed process; pasting JSON with trailing commas or single quotes into psql.","solutions":["Run the suggested reset: UPDATE remote_agent_codebases SET commands = '{}' WHERE id = '<id>'; then re-add commands via the API.","Inspect the raw value first (SELECT commands FROM remote_agent_codebases WHERE id='<id>') and fix the JSON syntax if recoverable (trailing commas, unescaped quotes).","Check application logs for db.codebase_commands_json_parse_failed entries — they include the raw value and parse error.","Validate any manual writes with SELECT commands::jsonb ... or jsonb_set to let PostgreSQL reject bad JSON at write time.","Backfill rows from a backup if the original commands matter and the corruption is old."],"exampleFix":"-- before: corrupt value\nSELECT commands FROM remote_agent_codebases WHERE id='abc'; -- \"{path: x, }\"\n-- after: reset to empty object per the error's guidance\nUPDATE remote_agent_codebases SET commands = '{}' WHERE id = 'abc';","handlingStrategy":"try-catch","validationCode":"// pre-flight sanity check on the stored value before calling getCodebaseCommands\nconst { rows } = await pool.query('SELECT commands FROM remote_agent_codebases WHERE id = $1', [id]);\nconst raw = rows[0]?.commands;\nif (typeof raw === 'string') {\n  try { JSON.parse(raw); } catch { await pool.query(\"UPDATE remote_agent_codebases SET commands = '{}' WHERE id = $1\", [id]); }\n}","typeGuard":"function isCommandsRecord(v: unknown): v is Record<string, { path: string; description: string }> {\n  return !!v && typeof v === 'object' && !Array.isArray(v) &&\n    Object.values(v).every(e => !!e && typeof e === 'object' && typeof e.path === 'string' && typeof e.description === 'string');\n}","tryCatchPattern":"let commands;\ntry {\n  commands = await getCodebaseCommands(id);\n} catch (e) {\n  if (e.message.startsWith('Corrupt commands JSON')) {\n    await pool.query(\"UPDATE remote_agent_codebases SET commands = '{}' WHERE id = $1\", [id]);\n    commands = await getCodebaseCommands(id); // reset worked\n  } else throw e;\n}","preventionTips":["Edit the commands column only through the application API, never raw psql, unless you validate with ::jsonb casts.","Declare the column as jsonb (or validate on write) so malformed JSON is rejected at INSERT/UPDATE time.","Watch logs for db.codebase_commands_json_parse_failed — it flags corruption early with the raw value.","Keep backups of remote_agent_codebases before manual database surgery."],"tags":["database","json","data-corruption","postgresql","persistence"],"backgroundTag":"corrupt-json-in-database","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}