farion1231 / farion1231/cc-switch

Bug: proxy produces empty content messages causing 400 error with llama.cpp

Open
#2,467 1 comment 0 reactions 0 assignees View on GitHub
stale
Dominant language
Rust
Stars
133k
Forks
9.2k
Avg merge
3d 20h
Merged PRs (30d)
48

Description

The cc-switch proxy in `src-tauri/src/proxy/providers/transform.rs` has two bugs in the Anthropic → OpenAI message conversion that produce empty content messages, which causes llama.cpp to reject with 400 Bad Request:

```
messages.0: all messages must have non-empty content except for the optional final assistant message
```

## Bug 1 (lines 98-114 + 201-210): System messages with empty text are not filtered

When the Anthropic request's `system` field is an array with a content block containing `"text": ""`, line 105 passes the `Some(text)` guard because `Some("")` is not `None`. A system message with `content: ""` is created. Then in `normalize_openai_system_messages` (line 201), the `system_count == 1` branch has NO content validation — the empty system message passes through untouched as `messages[0]`.

Compare with the `system_count > 1` branch (line 224) which correctly filters with `Some(Value::String(text)) if !text.is_empty()`.

**Fix**: Add `!text.is_empty()` guard at line 105, or add empty-content filtering in the `system_count == 1` branch.

## Bug 2 (lines 363-368): Assistant messages with tool_use but no text get `content: null`

When an assistant message's content array contains only `tool_use` blocks (no `text` blocks), `content_parts` is empty but `tool_calls` is non-empty. The code sets `msg["content"] = Value::Null` (line 368). While valid per OpenAI spec, llama.cpp rejects null content on non-final assistant messages.

**Fix**: When `content_parts` is empty but `tool_calls` is non-empty, either omit the `content` key entirely or set it to an empty string `""`.

## Reproduction

1. Set up cc-switch with `apiFormat: "openai_chat"` pointing to a local llama.cpp server
2. Send any request that triggers tool use or has system prompts with empty text blocks
3. llama.cpp returns 400

## Environment

- macOS
- cc-switch latest
- llama.cpp server with Qwen3 model

Contributor guide

Open the contributing guide

Research direction

Start in src-tauri/src/proxy/providers/transform.rs, especially the Anthropic system conversion around lines 98-114 and normalization around lines 201-224. Inspect the assistant conversion around lines 363-368, then reproduce against a local llama.cpp server using empty system text and tool_use-only assistant content. Done means the conversion no longer emits rejected empty or null messages and the request succeeds without a 400 response.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.