Hmbown/CodeWhale · error

Zen Chat Completions request should succeed

Error message

Zen Chat Completions request should succeed

What it means

Test-side `.expect("Zen Chat Completions request should succeed")` panic. `create_message` returned `Err` for a `WireFormat::ChatCompletions` client against the mocked `/v1/chat/completions` endpoint. The OpenAI-compatible chat completion path failed before completion — send failure, wrong route, or the mock's chat-completion JSON no longer parses into the client's response type.

Solutions

  1. Print the underlying error (`{e:?}`) to see send vs. parse failure.
  2. Verify the mock at `POST /v1/chat/completions` returns the complete fixture including `object`, `created`, `choices` and `usage`.
  3. Confirm `client.wire_format == WireFormat::ChatCompletions` (asserted above).
  4. Check auth: ChatCompletions uses `authorization: Bearer ...` and must not carry `anthropic-version`.

Example fix

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

Strategy: try-catch

Validate before calling

// Rust (preconditions)
assert_eq!(client.wire_format, WireFormat::ChatCompletions);
assert!(fixture["choices"].as_array().map_or(false, |c| !c.is_empty()));
assert!(fixture.get("usage").is_some());

Try / catch

match client.create_message(req).await {
    Ok(msg) => assert!(!msg.content.is_empty()),
    Err(e) => panic!("Chat Completions request should succeed: {e:?}"),
}

Prevention

When it happens

Trigger: Running `opencode_zen_chat_request_uses_chat_completions_route` when the mock path no longer matches, deepseek-v4-pro no longer resolves to ChatCompletions, or the fixture (missing `created`, `object`, `choices[].finish_reason`, `usage`) fails response parsing.

Common situations: Tightening the ChatCompletions response deserializer; renaming models in the route table so the test model falls to another wire; edited mock fixture dropping required fields.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

                "object": "chat.completion",
                "model": "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 = opencode_zen_client(&server, "deepseek-v4-pro");
        assert_eq!(client.wire_format, WireFormat::ChatCompletions);
        client
            .create_message(minimal_zen_request("deepseek-v4-pro"))
            .await
            .expect("Zen Chat Completions request should succeed");

        let requests = server.received_requests().await.expect("recorded request");
        assert_eq!(requests.len(), 1);
        assert_zen_bearer_without_codex_headers(&requests[0]);
        assert!(requests[0].headers.get("anthropic-version").is_none());
    }

    #[tokio::test]
    async fn opencode_zen_client_fails_closed_when_request_model_changes_protocol() {
        let server = MockServer::start().await;
        let client = opencode_zen_client(&server, "gpt-5.5");

        let error = client
            .create_message(minimal_zen_request("claude-sonnet-4-6"))
            .await
            .expect_err("a Responses-bound client must not send a Messages model");
        assert!(format!("{error:#}").contains("resolve a new model route"));
        assert!(

View on GitHub (pinned to 73e0f67d83)