ComposioHQ/composio · error · ToolFileUploadError
Failed to upload file to S3: ${uploadResponse.statusText}
Error message
Failed to upload file to S3: ${uploadResponse.statusText} What it means
After obtaining an upload URL, uploadFile PUTs the bytes to S3 with the file's Content-Type/Length. A non-ok upload response throws ToolFileUploadError with reason 'upload', including the S3 statusText.
Source
Thrown at ts/packages/cli/src/services/tool-file-uploads.ts:262
const presigned = await params.client.files.createPresignedURL({
filename: fileData.fileName,
mimetype: fileData.mimeType,
md5,
tool_slug: params.toolSlug,
toolkit_slug: params.toolkitSlug,
});
const uploadResponse = await fetch(presigned.new_presigned_url, {
method: 'PUT',
body: fileData.bytes,
headers: {
'Content-Type': fileData.mimeType,
'Content-Length': fileData.bytes.byteLength.toString(),
},
});
if (!uploadResponse.ok) {
throw new ToolFileUploadError({
message: `Failed to upload file to S3: ${uploadResponse.statusText}`,
reason: 'upload',
status: uploadResponse.status,
});
}
return {
name: fileData.fileName,
mimetype: fileData.mimeType,
s3key: presigned.key,
};
};
const hydrateFileUploads = async (
value: unknown,
schema: JsonSchema | undefined,
ctx: {
readonly fs: FileSystem.FileSystem;View on GitHub (pinned to 64b1b85502)
Solutions
- Retry the whole upload flow (fetch a fresh presigned URL) — most expiry/signature issues self-heal
- Ensure Content-Type sent matches what was declared when the URL was generated; don't modify the file between steps
- Reduce file size or chunk large uploads
- Check S3 status (health.aws.amazon.com) for ongoing incidents
Defensive patterns
Strategy: retry
Try / catch
catch (e) { if (e instanceof ToolFileUploadError && e.reason === 'upload') { return await uploadFileFreshUrl(); /* re-request presigned URL and retry */ } throw e; } Prevention
- Upload immediately after obtaining the presigned URL
- Keep Content-Type consistent between URL generation and PUT
- Retry transient S3 5xx with backoff
When it happens
Trigger: The presigned PUT fails server-side: signature/expiry mismatch on the presigned URL, request-size limits, altered headers (Content-Type changed after URL generation), or an S3 5xx.
Common situations: Delay between getting the presigned URL and uploading past its expiry, mutating the file bytes or mime type in between, very large files exceeding the presigned policy, or transient S3 errors.
Related errors
- Error downloading file: {_sanitize_url_for_logging(self.s3ur
- Error downloading file: {_sanitize_url_for_logging(self.s3ur
- Failed to upload file: ${uploadResponse.statusText}
- Failed to fetch file: ${response.statusText}
- Failed to upload file to S3: ${uploadResponse.statusText}
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/31f7b41060be12af.
Report an issue: GitHub.