{"record":{"id":"14eea6f6890899e2","repo":"stablyai/orca","slug":"a-claude-config-directory-path-is-required","errorCode":null,"errorMessage":"A Claude config directory path is required.","messagePattern":"A Claude config directory path is required\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/claude-accounts/service.ts","lineNumber":211,"sourceCode":"        captured\n      )\n    } catch (error) {\n      await this.cleanupFailedAdd(accountId, managedAuth.managedAuthPath, previousSettings, error)\n      throw error\n    }\n  }\n\n  // Why: capture credentials from a CLAUDE_CONFIG_DIR the caller already\n  // authenticated (e.g. a temp dir the CLI ran `claude login` into), mirroring\n  // runClaudeLoginAndCapture's capture step but without spawning the interactive\n  // login. On Linux/Windows the credentials live in a plaintext `.credentials.json`.\n  private async captureFromExistingConfigDir(\n    configDir: string,\n    previousLegacyCredentialsSha256?: string | null\n  ): Promise<CapturedClaudeAuth> {\n    const trimmed = configDir.trim()\n    if (!trimmed) {\n      throw new Error('A Claude config directory path is required.')\n    }\n    const resolvedDir = resolve(trimmed)\n    // Why: macOS keeps Claude credentials in the Keychain rather than a file, so\n    // only require `.credentials.json` off-darwin; captureAuthFromConfigDir reads\n    // the scoped Keychain item on macOS.\n    if (process.platform !== 'darwin' && !existsSync(join(resolvedDir, '.credentials.json'))) {\n      throw new Error(\n        `No Claude credentials found in ${resolvedDir}. Run \\`claude login\\` into this directory first.`\n      )\n    }\n    // Why: `allowFailure` covers a non-zero exit but not a spawn error, and unlike\n    // the GUI flow nothing has run `claude` in this process yet — a daemon started\n    // with a minimal PATH (launchd/systemd) would hard-fail an add the user already\n    // signed in for. Identity still resolves from the config dir's oauthAccount.\n    let status = ''\n    try {\n      status = await this.runClaudeCommand(\n        ['auth', 'status', '--json'],","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/claude-accounts/service.ts#L193-L229","documentation":"Thrown by captureFromExistingConfigDir() when the provided configDir trims to an empty string. The method requires a real CLAUDE_CONFIG_DIR path to read credentials from; an empty/whitespace-only argument is rejected before any filesystem work.","triggerScenarios":"Calling captureFromExistingConfigDir(''), captureFromExistingConfigDir('   '), or passing a path that becomes empty after .trim(). Typically an IPC handler or caller that forwarded an undefined/blank input.","commonSituations":"UI 'import from existing dir' form submitted empty. A programmatic caller passing undefined coerced to ''. A template/string concatenation bug producing an empty path.","solutions":["Validate configDir is a non-empty string at the caller (IPC handler) before invoking captureFromExistingConfigDir.","Provide a clear UI validation error for an empty directory field.","Default to a known CLAUDE_CONFIG_DIR if the user intends the default location."],"exampleFix":"// before\nconst trimmed = configDir.trim()\nif (!trimmed) {\n  throw new Error('A Claude config directory path is required.')\n}\n\n// after — caller\nif (!configDir?.trim()) {\n  return { error: 'Config directory is required' }\n}","handlingStrategy":"validation","validationCode":"if (!configDir || !configDir.trim()) {\n  throw new Error('Config directory path is required')\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate configDir at the IPC/UI boundary before calling the service.","Reject empty form submissions client-side.","Default to a known CLAUDE_CONFIG_DIR when appropriate."],"tags":["validation","claude-accounts","config-dir","input"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}