Skip to content

feat(core): surface S3 error details on upload failure#316

Merged
gregberge merged 3 commits into
mainfrom
improve-s3-error-handling
Jun 11, 2026
Merged

feat(core): surface S3 error details on upload failure#316
gregberge merged 3 commits into
mainfrom
improve-s3-error-handling

Conversation

@gregberge

Copy link
Copy Markdown
Member

Summary

When an upload to S3 fails, the user previously only saw a bare HTTP status (e.g. 403 Forbidden). S3 returns the real reason in an XML error body:

<Error>
  <Code>AccessDenied</Code>
  <Message>Request has expired</Message>
</Error>

This PR reads that body and includes the Code/Message in the thrown error, so failures now read like:

Failed to upload file to <url>: 403 Forbidden — AccessDenied: Request has expired

Changes

  • Added readS3ErrorMessage to extract <Code>/<Message> from the S3 error body (defensive: falls back to whichever field is present, returns null on unreadable/non-S3 bodies).
  • Added createUploadError to combine the HTTP status with that detail.
  • uploadFile and uploadFileWithPresignedPost now throw via this helper.
  • Added doc comments to both upload functions.

Notes

The error body is parsed with a non-greedy regex rather than a full XML parser, to avoid a dependency for S3's flat, well-known error shape.

🤖 Generated with Claude Code

Read the XML error body S3 returns on a failed upload and include the
Code/Message in the thrown error so users see the actual reason (e.g.
"AccessDenied: Request has expired") instead of a bare HTTP status.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 11, 2026 09:22
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
argos-js-sdk-reference Ready Ready Preview, Comment Jun 11, 2026 9:38am

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves upload failure diagnostics in @argos-ci/core by extracting S3’s XML error Code/Message and including them in thrown upload errors, making failures actionable instead of only showing an HTTP status.

Changes:

  • Added helpers to read S3 XML error details and build a richer upload error message.
  • Updated both presigned PUT and presigned POST upload paths to throw the richer error.
  • Added doc comments clarifying behavior of the upload functions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/core/src/s3.ts Outdated
Comment thread packages/core/src/s3.ts Outdated
Comment thread packages/core/src/s3.ts
Comment on lines +46 to +54
async function createUploadError(
url: string,
response: Response,
): Promise<Error> {
const detail = await readS3ErrorMessage(response);
const status = `${response.status} ${response.statusText}`;
return new Error(
`Failed to upload file to ${url}: ${status}${detail ? ` — ${detail}` : ""}`,
);
The upload e2e globs the whole __fixtures__ dir, including a 10MB PNG
that is sharp-optimized, hashed, and uploaded to S3 over the network.
That work sits right at the previous 15s limit and timed out in CI.
Raise it to 30s, consistent with the sibling skip test's 20s budget.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address review feedback: trim the Code/Message inner text (pretty-printed
XML leaves surrounding whitespace) and only append response.statusText
when present, since it's often empty in Node and would yield "403 ".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gregberge gregberge merged commit d913ac8 into main Jun 11, 2026
68 checks passed
@gregberge gregberge deleted the improve-s3-error-handling branch June 11, 2026 09:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants