Hmbown/CodeWhale · error
Codex client
Error message
Codex client
What it means
A panic from `CodewhaleClient::new(&config).expect("Codex client")` in the credential-snapshot test. Client construction resolves the Codex bearer token and account id from the OPENAI_CODEX_AUTH_FILE fixture (with OPENAI_CODEX_ACCESS_TOKEN / CODEX_ACCESS_TOKEN removed) and validates them; construction fails when credential resolution or required client setup fails — e.g. the auth file content is rejected or a TLS/crypto provider could not be initialized.
Solutions
- Validate the fixture auth.json is exactly {"tokens":{"access_token":<valid JWT>,"account_id":"..."}} and the JWT is well-formed base64url with future exp.
- Ensure crate::test_support::lock_test_env() guards OPENAI_CODEX_AUTH_FILE / OPENAI_CODEX_ACCESS_TOKEN / CODEX_ACCESS_TOKEN so parallel tests cannot leak values.
- Install the crypto provider before constructing clients (rustls::crypto::ring::default_provider().install_default()), as done in client_with_config_secret_sentinels.
- Run the single test with --test-threads=1 to rule out cross-test env pollution, then bisect.
Example fix
// before
let client = CodewhaleClient::new(&config).expect("Codex client");
// after (defensively, in test setup)
let _ = rustls::crypto::ring::default_provider().install_default();
let client = CodewhaleClient::new(&config)
.unwrap_or_else(|e| panic!("Codex client: {e:?}")); Defensive patterns
Strategy: validation
Validate before calling
// rust: pre-validate the fixture before constructing the client let json: serde_json::Value = serde_json::from_slice(&std::fs::read(&path)?)?; assert!(json["tokens"]["access_token"].is_string(), "fixture missing access_token"); assert!(json["tokens"]["account_id"].is_string(), "fixture missing account_id");
Try / catch
let client = CodewhaleClient::new(&config)
.unwrap_or_else(|e| panic!("Codex client construction failed: {e:?}")); Prevention
- Generate fixture JWTs with the shared test_support::future_test_jwt helper, never hand-written strings.
- Always pair EnvVarGuard set/remove with lock_test_env to prevent cross-test env leakage.
- Install the rustls ring provider in test setup before any client construction.
- Print the Err payload (debug) instead of bare expect when diagnosing.
When it happens
Trigger: `CodewhaleClient::new` returns Err in the test after OPENAI_CODEX_AUTH_FILE points at a fixture auth.json whose access_token fails JWT/base64 validation, whose required fields are missing, or when the rustls crypto provider is not installed.
Common situations: Editing the fixture JSON into an invalid shape, test env var leakage between tests (lock_test_env not held), expired/malformed hand-written JWTs, or rustls default provider contention with other tests.
Related errors
- canonical temp root
- client with secret sentinels
- Codewhale-owned OAuth credentials at
- credential fixture
- no usable runtime-effective API key
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1dd50f6afc2847fa.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/client.rs:8288
providers: Some(ProvidersConfig {
openai_codex: ProviderConfig {
auth_mode: Some("oauth".to_string()),
external_credentials: Some(
codewhale_config::ExternalCredentialConsentToml::read_only(
codewhale_config::ProviderKind::OpenaiCodex,
codewhale_config::ExternalCredentialSource::CodexCli,
path.clone(),
),
),
..ProviderConfig::default()
},
..ProvidersConfig::default()
}),
..Config::default()
};
crate::external_credentials::reset_side_effect_trap();
let client = CodewhaleClient::new(&config).expect("Codex client");
assert_eq!(client.api_key, token_a);
assert_eq!(client.codex_account_id.as_deref(), Some("account-a"));
assert_eq!(
crate::external_credentials::side_effect_trap_counts(),
(1, 1),
"bearer and account id must come from one secure open/read"
);
// An owner rotation after construction cannot splice account B into
// the already-resolved bearer snapshot.
std::fs::write(
&path,
serde_json::to_string(&serde_json::json!({"tokens": {"access_token": crate::test_support::future_test_jwt("b"), "account_id": "account-b"}})).expect("serialize rotated fixture"),
)
.expect("rotate fixture");
assert_eq!(client.api_key, token_a);
assert_eq!(client.codex_account_id.as_deref(), Some("account-a"));
}View on GitHub (pinned to 73e0f67d83)