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

  1. Check the status code in the message (404 = key not found, 403 = permission) and fix accordingly
  2. Verify the S3Object file key and storage value are correct
  3. Confirm the file exists (e.g. via the S3 file list API) before loading
  4. 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

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


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/a272222bd51649b6. Report an issue: GitHub.