{"record":{"id":"ceff7f2f6684c323","repo":"Hmbown/CodeWhale","slug":"external-credential-file-not-found-at","errorCode":null,"errorMessage":"external credential file not found at {}","messagePattern":"external credential file not found at (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/oauth.rs","lineNumber":1773,"sourceCode":"    store\n        .write(name, &serialized, allow_replace)\n        .with_context(|| {\n            format!(\n                \"writing owned OAuth credentials to {}\",\n                codewhale_config::quote_os_path(&store.directory().join(name))\n            )\n        })?;\n    #[cfg(test)]\n    crate::external_credentials::record_owned_credential_write();\n    Ok(())\n}\n\n/// Read-only parse of another CLI's granted credential file.\nfn load_external_auth_file(\n    grant: &codewhale_config::ExternalCredentialReadGrant,\n) -> Result<AuthFile> {\n    let Some(raw) = crate::external_credentials::read_to_string(grant)? else {\n        bail!(\n            \"external credential file not found at {}\",\n            codewhale_config::quote_os_path(grant.path())\n        );\n    };\n    parse_auth_file(&raw, grant.path())\n}\n\nfn select_entry(provider: OAuthProvider, file: &mut AuthFile) -> Option<(String, OwnedAuthEntry)> {\n    // Prefer this provider's registered client-id scope when present.\n    let preferred_suffix = format!(\"::{}\", oauth_provider_params(provider).default_client_id);\n    if let Some((k, v)) = file\n        .iter()\n        .find(|(k, e)| k.ends_with(&preferred_suffix) && entry_has_usable_secret(e))\n    {\n        return Some((k.clone(), v.clone()));\n    }\n    file.iter()\n        .find(|(_, e)| entry_has_usable_secret(e))","sourceCodeStart":1755,"sourceCodeEnd":1791,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/oauth.rs#L1755-L1791","documentation":"When consuming another CLI's credential file under a read-only `ExternalCredentialReadGrant`, the file at the granted path does not exist (or is unreadable as a string), so it cannot be parsed into an `AuthFile`. The library quotes the OS path in the message to make the missing file obvious.","triggerScenarios":"Calling `load_external_auth_file(grant)` where `crate::external_credentials::read_to_string(grant)` returns `None` — the path in the grant (`grant.path()`) has no file on disk.","commonSituations":"Pointing the external-credential grant at a path where `grok login` (or another CLI) never wrote its auth file; the other CLI not yet logged in; the file was deleted or lives under a different HOME; typo in the configured path.","solutions":["Run the other CLI's login first (e.g. `grok login`) so its credential file exists at the granted path.","Verify the configured external credential path matches the real file (check `~/.config/<cli>/auth.json` or equivalent).","Alternatively use Codewhale-owned storage via `codewhale auth xai-device` instead of importing."],"exampleFix":"// before (config)\nexternal_credential_path = \"/home/me/.grok/auth.json\"   // file absent\n// after\n$ grok login            # creates the auth file\ncodewhale ...           # import now finds it","handlingStrategy":"validation","validationCode":"use std::path::Path;\nlet path = grant.path();\nif !Path::new(path).is_file() {\n    // run `grok login` first or fix the configured path before importing\n}","typeGuard":"fn external_credential_exists(grant: &ExternalCredentialReadGrant) -> bool {\n    std::path::Path::new(grant.path()).is_file()\n}","tryCatchPattern":null,"preventionTips":["Run the external CLI's login before pointing Codewhale at its auth file.","Verify the configured path after OS/HOME changes (the file usually lives under the user's config dir).","Prefer Codewhale-owned storage (`codewhale auth xai-device`) when import is not required."],"tags":["file","credentials","external-cli"],"backgroundTag":"file-not-found","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}