Hmbown/CodeWhale · error · anyhow::Error

translate: Anthropic Messages response did not contain text

Error message

translate: Anthropic Messages response did not contain text content

What it means

The translate helper for the Anthropic Messages dialect concatenates every ContentBlock::Text block from the response, trims, and requires a non-empty result. If the model replied exclusively with non-text blocks (tool_use, thinking, server-tool output) or empty text, translation bails with this message rather than returning an empty string.

Source

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

        temperature: None,
        top_p: None,
    }
}

fn translation_text_from_response(response: &MessageResponse) -> Result<String> {
    let translated = response
        .content
        .iter()
        .filter_map(|block| match block {
            ContentBlock::Text { text, .. } => Some(text.as_str()),
            _ => None,
        })
        .collect::<Vec<_>>()
        .join("")
        .trim()
        .to_string();
    if translated.is_empty() {
        bail!("translate: Anthropic Messages response did not contain text content");
    }
    Ok(translated)
}

fn xiaomi_mimo_base_url_uses_token_plan(base_url: &str) -> bool {
    let normalized = base_url.trim().to_ascii_lowercase();
    let without_scheme = normalized
        .strip_prefix("https://")
        .or_else(|| normalized.strip_prefix("http://"))
        .unwrap_or(&normalized);
    let host = without_scheme
        .split(['/', '?', '#'])
        .next()
        .unwrap_or_default();
    let host = host.split(':').next().unwrap_or(host);
    host.starts_with("token-plan-") && host.ends_with(".xiaomimimo.com")
}

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Retry the request once — transient empty responses are common with LLMs.
  2. Adjust the prompt to demand plain prose and keep tool definitions out of it.
  3. Check the model/config: switch to a model known to return plain text for translation.

Example fix

// before
let translated = anthropic.translate(text).await?;

// after: retry once, then fail with context
let translated = match anthropic.translate(text).await {
    Ok(t) => t,
    Err(err) if err.to_string().contains("did not contain text content") => {
        anthropic.translate(text).await.context("model returned no text twice")?
    }
    Err(err) => return Err(err),
};
Defensive patterns

Strategy: retry

Try / catch

Retry the same request once, optionally adding an explicit 'reply with text only' instruction; if the second attempt still reports no text content, surface a model-configuration error instead of looping.

Prevention

When it happens

Trigger: Invoking the translate path when the model emits only a tool_use block, only thinking blocks, or empty text — typical when tool schemas leak into the translation prompt or a model is configured with forced tool choice.

Common situations: Translation prompts that include tool definitions; beta or reasoning models that emit non-text blocks by default; degenerate or refusal responses with no text payload.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/add467740d450b74. Report an issue: GitHub.