transloadit/uppy · error · S3ServiceError

S3 returned ${xhr.status}${serviceCode ? ` – ${serviceCode}`

Error message

S3 returned ${xhr.status}${serviceCode ? ` – ${serviceCode}` : ''}

What it means

Thrown by S3mini's request() when the S3 endpoint returns a non-2xx HTTP status that isn't a retryable/auth case. It wraps the status code, an optional parsed S3 service error Code, and the response body into a U.S3ServiceError so callers can inspect status and serviceCode.

Source

Thrown at packages/@uppy/aws-s3/src/s3-client/S3mini.ts:365

          shouldRetryCredentials &&
          this.getCredentials != null &&
          serviceCode != null &&
          ['ExpiredToken', 'InvalidAccessKeyId'].includes(serviceCode)
        ) {
          this.clearCachedCredentials()

          // Retry with fresh credentials
          return this.request({
            request,
            data,
            onProgress,
            signal,
            contentType,
            shouldRetryCredentials: false, // prevent infinite recursion
          })
        }

        throw new U.S3ServiceError(
          `S3 returned ${xhr.status}${serviceCode ? ` – ${serviceCode}` : ''}`,
          xhr.status,
          serviceCode,
          xhr.responseText,
        )
      }

      throw err
    }
  }

  /** Lists uploaded parts for a multipart upload. */
  public override async listParts({
    uploadId,
    key,
    signal,
  }: IT.ListPartsParams): Promise<IT.UploadPart[]> {
    this._checkKey(key)

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Inspect error.status and error.serviceCode (e.g. 'AccessDenied', 'NoSuchBucket', 'AuthorizationHeaderMalformed') to identify the cause
  2. Verify the endpoint/region and bucket configuration in the S3 mini client options
  3. Refresh or verify credentials if status is 403
  4. Retry with backoff on 5xx/503 SlowDown statuses

Example fix

// before
await s3Mini.putObject({ key, body })

// after
try {
  await s3Mini.putObject({ key, body })
} catch (err) {
  if (err instanceof S3ServiceError && err.status === 503) await retryLater()
  else throw err
}
Defensive patterns

Strategy: retry

Validate before calling

// Validate config before use
if (!endpoint || !credentials.accessKeyId) throw new Error('S3 client misconfigured')

Type guard

function isS3ServiceError(e: unknown): e is S3ServiceError {
  return e instanceof Error && 'status' in e && 'serviceCode' in e
}

Try / catch

try { await s3.call(...) } catch (e) { if (isS3ServiceError(e) && (e.status === 503 || e.status >= 500)) return backoffRetry(); throw e }

Prevention

When it happens

Trigger: Any S3 REST call (putObject, listParts, completeMultipartUpload, etc.) where xhr.status is an error: 400 (malformed XML/signature), 403 (bad credentials), 404 (wrong endpoint/bucket), 503 (slow down).

Common situations: Misconfigured endpoint URL or region, expired STS credentials, wrong bucket name, SigV4 signing mismatches, S3 rate limiting (503 SlowDown).

Related errors


AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28). Data as JSON: /api/errors/3a11192be5f2ca53. Report an issue: GitHub.