Hmbown/CodeWhale · error

Codewhale chat request should succeed

Error message

Codewhale chat request should succeed

What it means

This .expect("Codewhale chat request should succeed") is in crates/tui/src/client.rs:7804. It unwraps create_message() on a CodewhaleClient configured for WireFormat::ChatCompletions against a wiremock server. It panics when the chat-completions request fails — transport error, unexpected status, or response body the client can't parse into a message.

Solutions

  1. Inspect the panic payload: a status error names the code; a serde error names the field that no longer matches.
  2. Check the mock: it must accept the model "deepseek/deepseek-v4-pro" and return a valid chat-completions JSON body.
  3. Verify assert_codewhale_bearer's contract — Authorization: Bearer with the account key, never x-api-key — matches what the client now sends.
  4. If the wire schema intentionally changed, update both the client mapping and this test's mock/response fixture together.

Example fix

// before
client
    .create_message(minimal_zen_request("deepseek/deepseek-v4-pro"))
    .await
    .expect("Codewhale chat request should succeed");
// after
client
    .create_message(minimal_zen_request("deepseek/deepseek-v4-pro"))
    .await
    .unwrap_or_else(|e| panic!("Codewhale chat request should succeed: {e:?}"));
Defensive patterns

Strategy: try-catch

Try / catch

// log the failure detail instead of a bare expect
match client.create_message(minimal_zen_request(model)).await {
    Ok(msg) => { /* assertions */ }
    Err(e) => panic!("chat request failed: {e:?}"),
}

Prevention

When it happens

Trigger: Calling client.create_message(minimal_zen_request(...)) where the mounted mock route for ChatCompletions is missing/returns non-2xx or a body that fails deserialization; auth mismatch (the test requires the account key as Authorization: Bearer, never x-api-key) causing a mocked 401; wrong model id in the request path/body.

Common situations: Changing Codewhale's auth header from Bearer to x-api-key so the mock's auth guard rejects it; altering the ChatCompletions request/response schema; pointing the client at an unmocked URL path after a base-URL refactor.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/a7dd3f45e9753b2a. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/client.rs:7804

                "object": "chat.completion",
                "model": "deepseek/deepseek-v4-pro",
                "choices": [{
                    "index": 0,
                    "message": {"role": "assistant", "content": "ok"},
                    "finish_reason": "stop"
                }],
                "usage": {"prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2}
            })))
            .expect(1)
            .mount(&server)
            .await;

        let client = codewhale_client(&server, "deepseek/deepseek-v4-pro");
        assert_eq!(client.wire_format, WireFormat::ChatCompletions);
        client
            .create_message(minimal_zen_request("deepseek/deepseek-v4-pro"))
            .await
            .expect("Codewhale chat request should succeed");

        let requests = server.received_requests().await.expect("recorded request");
        assert_eq!(requests.len(), 1);
        assert_codewhale_bearer(&requests[0]);
        let body: Value = serde_json::from_slice(&requests[0].body).expect("chat JSON body");
        // Model ids reach the account API exactly as its catalog returns them.
        assert_eq!(
            body.get("model").and_then(Value::as_str),
            Some("deepseek/deepseek-v4-pro")
        );
    }

    #[tokio::test]
    async fn codewhale_messages_request_carries_the_account_bearer_not_x_api_key() {
        let server = MockServer::start().await;
        Mock::given(method("POST"))
            .and(path("/v1/messages"))
            .respond_with(ResponseTemplate::new(200).set_body_json(json!({

View on GitHub (pinned to 73e0f67d83)