{"record":{"id":"6f5772b678c56ee1","repo":"JuliusBrussee/caveman","slug":"managed-gemini-cli-routing-is-unsupported-because","errorCode":null,"errorMessage":"managed Gemini CLI routing is unsupported because Gemini CLI cannot send separate Caveman and upstream credentials","messagePattern":"managed Gemini CLI routing is unsupported because Gemini CLI cannot send separate Caveman and upstream credentials","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":6104,"sourceCode":"  const start = stripped.indexOf(GEMINI_NATIVE_ENV_BEGIN);\n  const finish = stripped.indexOf(GEMINI_NATIVE_ENV_END);\n  if ((start === -1) !== (finish === -1) || (start !== -1 && finish < start)) {\n    throw new Error(\"existing Gemini Caveman routing block is corrupted; run `caveman doctor gemini`\");\n  }\n  if (start !== -1) stripped = `${stripped.slice(0, start)}${stripped.slice(finish + GEMINI_NATIVE_ENV_END.length)}`.trim();\n  const block = [\n    GEMINI_NATIVE_ENV_BEGIN,\n    `GEMINI_BASE_URL=${route}`,\n    `GOOGLE_GEMINI_BASE_URL=${route}`,\n    `GOOGLE_VERTEX_BASE_URL=${appendUrlPath(route, \"/vertex\")}`,\n    GEMINI_NATIVE_ENV_END,\n  ].join(\"\\n\");\n  return { text: `${stripped}${stripped ? \"\\n\\n\" : \"\"}${block}\\n`, block };\n}\n\nfunction geminiNativeMutations(gw: string, mcpBinary: string): NativeMutation[] {\n  if (wrapMode(gw) === \"managed\") {\n    throw new Error(\"managed Gemini CLI routing is unsupported because Gemini CLI cannot send separate Caveman and upstream credentials\");\n  }\n  const settingsPath = geminiSettingsPath();\n  const settingsBefore = fileBytes(settingsPath);\n  const settings = parseJsonFileObject(settingsPath, settingsBefore);\n  assertNativeHooksShape(settingsPath, settings, \"gemini\");\n  if (settings.mcpServers !== undefined && (typeof settings.mcpServers !== \"object\" || settings.mcpServers === null || Array.isArray(settings.mcpServers))) {\n    throw new Error(`${settingsPath} mcpServers must be a JSON object; refusing to overwrite it`);\n  }\n  const servers = settings.mcpServers && typeof settings.mcpServers === \"object\" && !Array.isArray(settings.mcpServers)\n    ? settings.mcpServers as Record<string, unknown>\n    : {};\n  const previousMcp = servers.caveman;\n  const installedMcp = { command: mcpBinary, args: [] };\n  servers.caveman = installedMcp;\n  settings.mcpServers = servers;\n  const withHooks = nativeHooksDocument(\"gemini\", true, settings);\n\n  const envPath = join(homedir(), \".gemini\", \".env\");","sourceCodeStart":6086,"sourceCodeEnd":6122,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/cli/src/index.ts#L6086-L6122","documentation":"geminiNativeMutations() hard-refuses managed mode up front: wrapMode(gw) === \"managed\" means credentials flow through a managed gateway, but Gemini CLI cannot send separate Caveman and upstream credentials, so there is no safe way to route it. This is a designed capability gap, not a corrupted state.","triggerScenarios":"Passing a gateway URL whose wrap mode resolves to \"managed\" (e.g. a shared/remote caveman gateway) to the native Gemini integration command.","commonSituations":"Pointing caveman at a team-managed gateway via config/env and then trying to enable Gemini native routing; reusing gateway settings copied from a managed deployment.","solutions":["Use a local gateway (default wrap mode) for Gemini: point the integration at a locally running caveman instance","Change the gateway configuration so wrapMode resolves to \"local\" for the Gemini install command","Keep Gemini un-integrated on managed setups — this limitation is intentional and has no config workaround"],"exampleFix":"# before\n$ caveman native install gemini --gateway https://managed.example.com  # wrap mode: managed -> throws\n\n# after\n$ caveman serve &  # local gateway\n$ caveman native install gemini  # local wrap mode, succeeds","handlingStrategy":"validation","validationCode":"function gatewaySupportsGemini(gatewayUrl: string): boolean {\n  // managed wrap mode is a hard capability gap for Gemini\n  return new URL(gatewayUrl).hostnameIsLocalOrLoopback(); // local wrap mode only\n}","typeGuard":null,"tryCatchPattern":"try { nativeInstallGemini(gateway); } catch (e) {\n  if (e instanceof Error && /managed Gemini CLI routing is unsupported/.test(e.message)) {\n    skipOrUseLocalGateway(\"gemini\"); // no retry: capability gap, not transient\n  } else throw e;\n}","preventionTips":["Gate Gemini integration on local wrap mode in your setup scripts","Do not copy managed-gateway config into environments where you need Gemini routing","Treat this error as permanent for the given gateway; switch gateways rather than retrying"],"tags":["gemini","gateway","managed-mode","unsupported-operation","credentials"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}