zeroclaw-labs/zeroclaw · error · SemanticEmptyTerminalCompletion
provider completed without final text or tool calls
Error message
provider completed without final text or tool calls
What it means
Anthropic provider: when a native structured completion is projected into the legacy string-only API, require_terminal_text checks is_semantically_empty_terminal() first and raises the shared typed SemanticEmptyTerminalCompletion (so delivery boundaries keep the terminal cause). If the response has text = None at all, it also logs an ERROR before erroring. Typical cause: extended thinking consumed the budget, so no final answer block was produced.
Source
Thrown at crates/zeroclaw-providers/src/anthropic.rs:1855
"stop_reason": stop_reason,
"content_block_count": content_block_count,
"content_block_types": content_block_types,
"native_tool_call_count": parsed.tool_calls.len(),
"has_reasoning": parsed.reasoning_content.is_some(),
})),
"Anthropic response completed without final text or tool calls"
);
}
parsed
}
/// Project a native completion into the legacy string-only API without
/// erasing the terminal semantic cause required by Reliable and SOP
/// delivery boundaries.
fn require_terminal_text(parsed: ProviderChatResponse) -> anyhow::Result<String> {
if parsed.is_semantically_empty_terminal() {
return Err(anyhow::Error::new(
zeroclaw_api::model_provider::SemanticEmptyTerminalCompletion,
));
}
parsed.text.ok_or_else(|| {
::zeroclaw_log::record!(
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure),
"anthropic: empty text in response"
);
anyhow::Error::msg("No response from Anthropic")
})
}
/// Resolve thinking parameters for an API request. Returns the effective
/// temperature (forced to 1.0 when thinking is active), the thinking
/// config for the request body, and the effective max_tokens (raised to
/// meet budget_tokens minimum when needed).View on GitHub (pinned to 88bb9c8533)
Solutions
- Raise max_tokens so thinking completes and a final text block is produced.
- Call the structured chat API (chat/chat_with_tools) instead of the string projection when tool_use blocks are expected; native tool calls are a valid terminal there.
- Disable forced thinking for string-only callers.
- Chain a fallback model via the reliable provider to absorb semantic-empty terminals.
Example fix
// before
let text = anthropic.chat_with_system(Some(sys), prompt, "claude-3-7", None).await?;
// model thinks to the token limit -> SemanticEmptyTerminalCompletion
// after
let text = anthropic.chat_with_system_opts(Some(sys), prompt, model, None, ChatOptions { max_tokens: 8192, thinking: Thinking::Off, ..Default::default() }).await?; Defensive patterns
Strategy: fallback
Validate before calling
fn has_final_text(resp: &ProviderChatResponse) -> bool {
!resp.is_semantically_empty_terminal() && resp.text.as_deref().map(|t| !t.trim().is_empty()).unwrap_or(false)
} Try / catch
match anthropic.chat_with_system(system, message, model, temp).await {
Ok(text) => Ok(text),
Err(e) if e.is::<SemanticEmptyTerminalCompletion>() => non_reasoning_provider().chat_with_system(system, message, model2, temp).await,
Err(e) => Err(e),
} Prevention
- Budget max_tokens above the model's extended-thinking spend for string-only callers.
- Turn thinking off for integrations that only need the final answer.
- Reserve string projections for display; use the structured chat API inside agent loops.
When it happens
Trigger: chat_with_system (string API) on the Anthropic provider returns a completion whose content blocks are only thinking blocks, or empty, or stop_reason 'max_tokens' fires inside the thinking phase: the projection to String finds no final text and raises the typed error.
Common situations: Extended-thinking models with max_tokens set too low, thinking forced via API options while the caller expects plain text, beta header/feature mismatch returning empty content, Claude models answering entirely in tool_use blocks when the string API was called without tools.
Related errors
- provider completed without final text or tool calls
- provider completed without final text or tool calls
- provider completed without final text or tool calls
- provider completed without final text or tool calls
- provider completed without final text or tool calls
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/775c96d56c5a0871.
Report an issue: GitHub.