windmill-labs/windmill · error · std::io::Error
e.to_string() (Bedrock stream receive error wrapped in io::E
Error message
e.to_string() (Bedrock stream receive error wrapped in io::Error, propagated to the AI streaming response)
What it means
In the Bedrock AI provider's SSE proxy (`sdk_stream_to_sse`), the stream of events from the AWS Bedrock SDK is converted into server-sent-event chunks. When the SDK's event stream returns an error mid-stream, the code wraps `e.to_string()` in a fresh `std::io::Error` (kind `Other`) and yields it downstream before breaking the loop. The original error type is lost — only its string survives — so consumers see a generic io error whose message is the underlying Bedrock error.
Source
Thrown at backend/windmill-ai/src/providers/bedrock.rs:474
let created = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
async_stream::stream! {
let mut stream = stream;
let mut state = BedrockSseStreamState::new(id, model, created);
loop {
match stream.recv().await {
Ok(Some(event)) => {
for chunk in bedrock_sse_chunks_for_event(&event, &mut state) {
yield Ok(chunk);
}
}
Ok(None) => break,
Err(e) => {
yield Err(std::io::Error::new(
std::io::ErrorKind::Other,
e.to_string(),
));
break;
}
}
}
yield Ok(Bytes::from("data: [DONE]\n\n"));
}
}
#[derive(Debug)]
struct BedrockSseStreamState {
id: String,
model: String,
created: u64,
tool_calls: HashMap<usize, (String, String, String)>,View on GitHub (pinned to e474e8803c)
Solutions
- Inspect the wrapped message in the io error — it contains the real Bedrock error (throttle/access denied/etc.) and act on that cause
- Check IAM permissions for `bedrock:InvokeModelWithResponseStream` and model access grants in the region
- Add retry/backoff for throttling errors on the client side
- Verify AWS credentials/region configuration; refresh long-lived sessions
Defensive patterns
Strategy: retry
Validate before calling
// before streaming, verify credentials and model access
await bedrock.send(new InvokeModelCommand({ modelId, body: smallProbe })); Try / catch
try {
await streamAiResponse();
} catch (e) {
const msg = String(e.cause ?? e);
if (/ThrottlingException/i.test(msg)) await backoffRetry();
else if (/AccessDenied/i.test(msg)) fixIamPermissions();
} Prevention
- Pre-validate Bedrock IAM permissions and model access in the target region
- Apply client-side backoff for throttling during bursts
- Refresh AWS credentials for long-running generations
- Monitor the wrapped message — the real Bedrock error text is inside the io error
When it happens
Trigger: The Bedrock runtime SDK's `receive_event` / stream returns `Err` while streaming a model response: throttling (TooManyRequests), model access denied, expired AWS credentials, stream timeouts, or the model endpoint aborting the stream mid-generation.
Common situations: Hitting Bedrock rate limits during bursts of AI requests, IAM policies missing `bedrock:InvokeModelWithResponseStream`, AWS credentials expiring during a long generation, region/model-id misconfiguration surfacing only mid-stream.
Related errors
- No response body for SSE stream
- Failed to fetch foundation models for AWS Bedrock
- SSE error: ${previewJobUpdates}
- err (multipart field stream error converted to io::Error dur
- Service error: {} (details: {:?})
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/97aff747f49d7a73.
Report an issue: GitHub.