windmill-labs/windmill · error · Error
Failed to load S3 file: ${response.status} ${response.status
Error message
Failed to load S3 file: ${response.status} ${response.statusText} - ${errorText} What it means
Thrown after the raw fetch to the job_helpers/download_s3_file endpoint when the response is not ok. Raw fetch is used because the generated OpenAPI client mishandles Blob responses, so the server's error body is read manually and inlined — the message carries the HTTP status plus the API's error detail (missing object, wrong key, denied permission).
Source
Thrown at typescript-client/client.ts:978
}
const queryParams = new URLSearchParams(params);
const w = workspace ?? getWorkspace();
// We use raw fetch here b/c OpenAPI generated client doesn't handle Blobs nicely
const response = await fetch(
`${OpenAPI.BASE}/w/${w}/job_helpers/download_s3_file?${queryParams}`,
{
method: "GET",
headers: {
Authorization: `Bearer ${OpenAPI.TOKEN}`,
},
}
);
// Check if the response was successful
if (!response.ok) {
const errorText = await response.text();
throw new Error(
`Failed to load S3 file: ${response.status} ${response.statusText} - ${errorText}`
);
}
return response.blob();
}
/**
* Persist a file to the S3 bucket. If the s3ResourcePath is undefined, it will default to the workspace S3 resource.
*
* ```typescript
* const s3object = await writeS3File(s3Object, "Hello Windmill!")
* const fileContentAsUtf8Str = (await s3object.toArray()).toString('utf-8')
* console.log(fileContentAsUtf8Str)
* ```
*
* @param workspace - Workspace to write to (defaults to the `WM_WORKSPACE` env var)
*/View on GitHub (pinned to e474e8803c)
Solutions
- Check the status code in the message (404 = key not found, 403 = permission) and fix accordingly
- Verify the S3Object file key and storage value are correct
- Confirm the file exists (e.g. via the S3 file list API) before loading
- Ensure the workspace is correct and the token has S3 read access
Example fix
// before
const blob = await loadS3File({ s3: 'data/file.json' })
// after
try {
const blob = await loadS3File({ s3: 'data/file.json' })
} catch (e) {
if (String(e.message).includes('404')) console.error('S3 file does not exist')
throw e
} Defensive patterns
Strategy: try-catch
Try / catch
try {
const blob = await loadS3File(s3Object, workspace)
} catch (e) {
if (String(e.message).startsWith('Failed to load S3 file:')) {
const status = Number(String(e.message).match(/(\d{3})/)?.[1])
if (status === 404) console.error('S3 key not found')
else if (status === 403) console.error('No permission for S3 object')
} else throw e
} Prevention
- Verify keys exist via the S3 file list API before loading
- Confirm workspace and storage values match where the file was written
- Handle presigned/permission expiry in long-running processes
When it happens
Trigger: Calling the S3 file load helper when the file key does not exist, the workspace/storage is wrong, or the caller lacks permission on the S3 object.
Common situations: Stale or mistyped S3 file key; file deleted upstream; wrong workspace; storage misconfiguration; expired presigned access.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Could not write file to S3
- ApiError with mapped HTTP status message (e.g. "Not Found",
- Generic Error: status: ${errorStatus}; status text: ${errorS
- Couldn't fetch resource types from hub ${hubBaseUrl}: ${(awa
- Couldn't fetch resource types from public hub:
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/a272222bd51649b6.
Report an issue: GitHub.