{"record":{"id":"8a8194c96daf58ee","repo":"JuliusBrussee/caveman","slug":"aider-integration-journal-lacks-owned-blocks","errorCode":null,"errorMessage":"Aider integration journal lacks owned blocks","messagePattern":"Aider integration journal lacks owned blocks","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":8388,"sourceCode":"    const mcp = root.mcp && typeof root.mcp === \"object\" && !Array.isArray(root.mcp) ? root.mcp as Record<string, unknown> : {};\n    if (mcp.caveman !== undefined && JSON.stringify(mcp.caveman) !== JSON.stringify(operation.owned?.installed_mcp)) {\n      throw new Error(\"OpenCode caveman MCP entry changed after enable; refusing destructive disable\");\n    }\n    if (mcp.caveman !== undefined) {\n      if (operation.owned?.previous_mcp === null || operation.owned?.previous_mcp === undefined) delete mcp.caveman;\n      else mcp.caveman = operation.owned.previous_mcp;\n    }\n    if (Object.keys(mcp).length > 0) root.mcp = mcp;\n    else delete root.mcp;\n    return jsonBytes(root);\n  }\n  if (operation.kind === \"aider-config\") {\n    let text = current.toString(\"utf8\");\n    const routeBlock = operation.owned?.route_block;\n    const readBlock = operation.owned?.read_block;\n    const previousRouteLine = operation.owned?.previous_route_line;\n    if (typeof routeBlock !== \"string\" || typeof readBlock !== \"string\") {\n      throw new Error(\"Aider integration journal lacks owned blocks\");\n    }\n    if (!text.includes(routeBlock) || !text.includes(readBlock)) {\n      throw new Error(\"Aider Caveman config block changed after enable; refusing destructive disable\");\n    }\n    text = text.replace(routeBlock, typeof previousRouteLine === \"string\" ? previousRouteLine : \"\");\n    text = text.replace(readBlock, \"\");\n    return Buffer.from(text.replace(/\\n{3,}/g, \"\\n\\n\"));\n  }\n  if (operation.kind === \"aider-core\") {\n    throw new Error(`${operation.file} changed after enable; refusing destructive disable`);\n  }\n  if (operation.kind === \"hermes-plugin-manifest\" || operation.kind === \"hermes-plugin-init\") {\n    throw new Error(`${operation.file} changed after enable; refusing destructive disable`);\n  }\n  if (operation.kind === \"hermes-config\") {\n    let text = current.toString(\"utf8\");\n    const routeBlock = operation.owned?.route_block;\n    const previousRouteLines = operation.owned?.previous_route_lines;","sourceCodeStart":8370,"sourceCodeEnd":8406,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/index.ts#L8370-L8406","documentation":"Aider disable requires the enable journal (operation.owned) to contain the exact route_block and read_block strings that were injected into the Aider config. If either is missing (not a string), the rollback cannot be performed safely, so the tool throws. This is a journal-corruption / missing-state error, not a config error.","triggerScenarios":"Running the disable operation with operation.kind === \"aider-config\" while operation.owned.route_block or operation.owned.read_block is undefined or not a string — e.g. journal written by an older version, partially written, or hand-deleted.","commonSituations":"Version upgrade changed the journal schema; state file truncated or edited; disabling on a machine where the state was synced incompletely.","solutions":["Delete/rename the stale journal state and manually remove the Caveman blocks from .aider.conf.yml.","Re-run enable to regenerate a complete journal, then disable.","Upgrade the CLI so journal reader and writer use the same schema."],"exampleFix":"// journal state missing blocks (corrupt)\n{ \"kind\": \"aider-config\", \"owned\": { \"route_block\": null } }\n// after: re-enable to regenerate\n{ \"kind\": \"aider-config\", \"owned\": { \"route_block\": \"# caveman-start ...\", \"read_block\": \"# caveman-read ...\" } }","handlingStrategy":"validation","validationCode":"const owned = journal.owned ?? {};\nif (typeof owned.route_block !== 'string' || typeof owned.read_block !== 'string') {\n  throw new Error('Aider journal incomplete; re-enable before disabling');\n}","typeGuard":"const hasAiderBlocks = (owned) =>\n  typeof owned?.route_block === 'string' && owned.route_block.length > 0 &&\n  typeof owned?.read_block === 'string' && owned.read_block.length > 0;","tryCatchPattern":"try {\n  await caveman.disable(['aider']);\n} catch (err) {\n  if (err.message.includes('journal lacks owned blocks')) {\n    console.error('Journal corrupt/incomplete; remove blocks from .aider.conf.yml manually.');\n  } else throw err;\n}","preventionTips":["Never hand-edit or prune the Caveman state/journal files.","Use the same CLI version for enable and disable.","Re-enable before disabling if you suspect journal corruption.","Keep a backup of .aider.conf.yml from before enable."],"tags":["journal","aider","disable-safety"],"backgroundTag":"missing-required-config-field","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}