{"record":{"id":"4ba193ca3c54f70d","repo":"JuliusBrussee/caveman","slug":"existing-hermes-caveman-native-block-is-unjournale","errorCode":null,"errorMessage":"existing Hermes Caveman native block is unjournaled; run `caveman doctor hermes`","messagePattern":"existing Hermes Caveman native block is unjournaled; run `caveman doctor hermes`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":7730,"sourceCode":"  end: string,\n  blockLines: string[],\n): string | null {\n  const section = topLevelSection(lines, sectionName);\n  if (section) {\n    if (sectionHasChildKey(lines, section, childName)) return null;\n    lines.splice(section.start + 1, 0, ...blockLines);\n    return blockLines.join(\"\\n\");\n  }\n  if (lines.length > 0 && lines[lines.length - 1]!.trim()) lines.push(\"\");\n  const body = blockLines.filter((line) => !line.includes(begin) && !line.includes(end));\n  const whole = [begin, `${sectionName}:`, ...body, end];\n  lines.push(...whole);\n  return whole.join(\"\\n\");\n}\n\nfunction hermesNativeConfig(source: string, gw: string, mcpBinary: string): { text: string; owned: Record<string, unknown> } {\n  for (const marker of [HERMES_NATIVE_ROUTE_BEGIN, HERMES_NATIVE_ROUTE_END, HERMES_NATIVE_PLUGIN_BEGIN, HERMES_NATIVE_PLUGIN_END, HERMES_NATIVE_MCP_BEGIN, HERMES_NATIVE_MCP_END]) {\n    if (source.includes(marker)) throw new Error(\"existing Hermes Caveman native block is unjournaled; run `caveman doctor hermes`\");\n  }\n  const lines = yamlLines(source);\n  let model = topLevelSection(lines, \"model\");\n  if (!model) {\n    lines.unshift(\"model:\");\n    model = topLevelSection(lines, \"model\")!;\n  }\n  const routeIndexes: number[] = [];\n  const previousRouteLines: string[] = [];\n  for (let i = model.start + 1; i < model.end; i++) {\n    if (/^  (provider|base_url):/.test(lines[i]!)) {\n      routeIndexes.push(i);\n      previousRouteLines.push(lines[i]!);\n    }\n  }\n  if (new Set(routeIndexes.map((index) => lines[index]!.match(/^  ([^:]+):/)?.[1])).size !== routeIndexes.length) {\n    throw new Error(\"Hermes model provider/base_url keys are duplicated; refusing ambiguous install\");\n  }","sourceCodeStart":7712,"sourceCodeEnd":7748,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/index.ts#L7712-L7748","documentation":"hermesNativeConfig() refuses to edit the Hermes config if it already contains any Caveman native block markers (route, plugin, or MCP begin/end). Presence of these markers means a prior install was not journaled, so the installer cannot safely transform the config and tells the user to run `caveman doctor hermes`.","triggerScenarios":"Running the Hermes enable/install flow when the Hermes YAML config already includes HERMES_NATIVE_ROUTE/PLUGIN/MCP BEGIN or END marker lines from an earlier, unjournaled install.","commonSituations":"An install that crashed between writing the config and updating the journal; restoring the Hermes config from a backup that contains blocks; copying a configured config.yaml from another machine; journal files deleted manually.","solutions":["Run `caveman doctor hermes` to strip/reconcile the stale blocks, then re-run enable.","Manually delete the Caveman marker-delimited blocks (route, plugin, MCP) from the Hermes config, then re-run install.","Restore the Hermes config to its pre-Caveman state from backup and re-run the enable flow."],"exampleFix":"// before (hermes config.yaml)\nmodel:\n  # caveman:native-route-begin\n  provider: \"custom\"\n  # caveman:native-route-end\n// after `caveman doctor hermes`\nmodel:\n  provider: \"anthropic\"","handlingStrategy":"validation","validationCode":"const cfg = readFileSync(hermesCfg, 'utf8');\nconst markers = [ROUTE_BEGIN, ROUTE_END, PLUGIN_BEGIN, PLUGIN_END, MCP_BEGIN, MCP_END];\nif (markers.some((m) => cfg.includes(m))) {\n  // run `caveman doctor hermes` before enabling\n}","typeGuard":null,"tryCatchPattern":"try {\n  await cavemanEnableHermes();\n} catch (e) {\n  if (String(e.message).includes('unjournaled')) {\n    await cavemanDoctorHermes();\n    await cavemanEnableHermes();\n  }\n}","preventionTips":["Use the Caveman CLI (not manual config edits) to enable/disable Hermes integration.","Run `caveman doctor hermes` after restoring the Hermes config from backup.","Do not manually delete journal state while config blocks remain.","Avoid copying configured Hermes configs between machines without running doctor."],"tags":["hermes","config","drift","install"],"backgroundTag":"conflicting-config-options","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"}