BoundaryML/baml · error

Expected message output in response, but is type

Error message

Expected message output in response, but is type {}

What it means

After calling Bedrock Converse, chat_anyhow expects response.output to be the ConverseOutput::Message variant. Any other variant (or None) means the model didn't return a message output, so the client bails. Note the current implementation always formats the type as the literal 'unknown', so the error doesn't tell you which variant it actually saw.

Solutions

  1. Check AWS guardrail configuration for the model — guardrail-intervened outputs are not returned as message output.
  2. Verify the model ID in client options supports the Converse API and returns message outputs.
  3. Retry the request; if persistent, enable logging/dumping the raw ConverseOutput to see the actual variant.
Defensive patterns

Strategy: retry

Try / catch

try:
    out = baml_client.MyFunction(...)
except Exception as e:
    if 'Expected message output in response' in str(e):
        log_raw_converse_output(...)  # inspect guardrails/stop reason
        out = retry_with_backoff(baml_client.MyFunction, ...)
    else:
        raise

Prevention

When it happens

Trigger: Bedrock Converse returns output other than a message — e.g. the response is empty, the request was consumed by a guardrail, or the model produced a non-message output type — while calling chat on an aws-bedrock client.

Common situations: Guardrails intercepting the response; model misconfiguration where the invoked model ID doesn't support Converse message output; transient empty responses from the service.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/1cd7fe1d449ca678. Report an issue: GitHub.

Appendix: source

Thrown at engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs:686

            // Adding a custom http client (above) breaks the stalled stream protection for some reason. If a bedrock request takes longer than 5s (the default grace period, it makes it error out), so we disable it.
            .stalled_stream_protection(StalledStreamProtectionConfig::disabled())
            .interceptor(CollectorInterceptor::new(
                call_stack,
                http_request_id.clone(),
                &self.properties,
            ));

        // Set endpoint_url if specified
        if let Some(endpoint_url) = self.properties.endpoint_url.as_ref() {
            bedrock_config = bedrock_config.endpoint_url(endpoint_url);
        }

        Ok(BedrockRuntimeClient::from_conf(bedrock_config.build()))
    }

    async fn chat_anyhow(&self, response: &ConverseOutput) -> Result<String> {
        let Some(bedrock::types::ConverseOutput::Message(ref message)) = response.output else {
            anyhow::bail!(
                "Expected message output in response, but is type {}",
                "unknown"
            );
        };
        // Try to extract text from all content blocks
        let mut extracted_text = String::new();
        let mut has_text = false;

        if message.content.is_empty() {
            anyhow::bail!("Expected message output to have content, but content is empty");
        }

        for content_block in &message.content {
            if let bedrock::types::ContentBlock::Text(text) = content_block {
                has_text = true;
                extracted_text.push_str(text);
            }
        }

View on GitHub (pinned to bd85ce9dee)