windmill-labs/windmill · error
upload_s3_file request to {url} failed with status {status}:
Error message
upload_s3_file request to {url} failed with status {status}: {body} What it means
upload_s3_file uploads content through the workspace's S3 file API and raises this error for any non-200 response, including the target URL, status code, and response body. Unlike the empty-message errors nearby, this one is fully contextualized.
Source
Thrown at backend/windmill-common/src/client.rs:298
reqwest::header::ACCEPT,
reqwest::header::HeaderValue::from_static("application/json"),
)
.header(
reqwest::header::AUTHORIZATION,
reqwest::header::HeaderValue::from_str(&format!("Bearer {}", self.token))
.map_err(|e| anyhow::anyhow!(e.to_string()))?,
)
.body(Body::wrap_stream(body))
.send()
.await
.context(format!("Failed to send upload_s3_file request to {url}"))?;
match response.status().as_u16() {
200u16 => Ok(()),
_ => {
let status = response.status();
let body = response.text().await.unwrap_or_default();
Err(anyhow::anyhow!(
"upload_s3_file request to {url} failed with status {status}: {body}"
))
}
}
}
pub async fn download_s3_file(
&self,
workspace_id: &str,
file_key: &str,
storage: Option<String>,
) -> anyhow::Result<bytes::Bytes> {
let mut query = vec![("file_key", file_key.to_string())];
if let Some(storage) = storage {
query.push(("storage", storage));
}
let response = self
.force_clientView on GitHub (pinned to e474e8803c)
Solutions
- Read the status and body in the message: 404 usually means the route/storage is missing, 413 means size limits, 5xx means upstream storage trouble
- Verify workspace large-file/S3 storage configuration in instance settings
- Confirm the backend was built with the parquet feature for S3 endpoints
- Check the S3/MinIO backend is reachable and credentials valid
- Retry transient 5xx with backoff
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: confirm storage configured (workspace large-file/S3 settings) before upload.
if file_len > MAX_UPLOAD { anyhow::bail!("file too large for s3 upload: {file_len}"); } Try / catch
match client.upload_s3_file(...).await {
Err(e) if e.to_string().contains("status 413") => anyhow::bail!("file exceeds storage size limit"),
Err(e) if e.to_string().contains("status 5") => { tokio::time::sleep(Duration::from_secs(2)).await; client.upload_s3_file(...).await }
other => other,
} Prevention
- Configure and health-check workspace large-file/S3 storage before enabling upload features
- Build the backend with the parquet feature wherever S3 endpoints are used
- Enforce client-side size limits to avoid 413s
- Retry only 5xx; treat 4xx as config/permission fixes
When it happens
Trigger: Upload of a file to the S3 storage endpoint returns 4xx/5xx: storage not configured for the workspace (400/404), file too large or quota exceeded (413), invalid s3 path or bad request (400), auth failure (401/403), or upstream S3/MinIO errors surfaced as 5xx.
Common situations: Workspace large-file storage misconfigured or pointing at an unreachable MinIO/S3, missing parquet feature so the route is absent, uploading during a storage outage, wrong resource path used for the S3 bucket.
Related errors
- Failed to load S3 file: ${response.status} ${response.status
- Could not write file to S3
- error writing file to {path}: {e:#}
- Recording upload failed: ${error.message}
- ApiError with mapped HTTP status message (e.g. "Not Found",
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/f6ca4a07adf21ea7.
Report an issue: GitHub.