transloadit/uppy · error · TypeError

[s3mini] uploadId must be a non-empty string

Error message

[s3mini] uploadId must be a non-empty string

What it means

A parameter guard inside _validateUploadPartParams, invoked by uploadPart, requiring `uploadId` to be a non-empty string. The uploadId is the token S3 returns from createMultipartUpload and identifies the multipart session; without it the part cannot be associated with any upload. Throws a TypeError when uploadId is missing, not a string, or whitespace.

Source

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

      const msg = `${C.ERROR_ENDPOINT_FORMAT} But provided: "${raw}"`
      throw new TypeError(msg)
    }
  }

  private _checkKey(key: string): void {
    if (typeof key !== 'string' || key.trim().length === 0) {
      throw new TypeError(C.ERROR_KEY_REQUIRED)
    }
  }

  private _validateUploadPartParams(
    key: string,
    uploadId: string,
    partNumber: number,
  ): void {
    this._checkKey(key)
    if (typeof uploadId !== 'string' || uploadId.trim().length === 0) {
      throw new TypeError(C.ERROR_UPLOAD_ID_REQUIRED)
    }
    if (!Number.isInteger(partNumber) || partNumber <= 0) {
      throw new TypeError(
        `${C.ERROR_PREFIX}partNumber must be a positive integer`,
      )
    }
  }

  /**
   * Uploads an object to S3 using XHR for progress tracking.
   */
  public override async putObject({
    key,
    data,
    fileType = C.DEFAULT_STREAM_CONTENT_TYPE,
    onProgress,
    signal,
  }: IT.PutObjectParams) {

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Capture and reuse the uploadId returned from createMultipartUpload: `const { uploadId, key } = await s3.createMultipartUpload(...)` then pass it to every uploadPart call.
  2. If resuming, persist {key, uploadId} (e.g. localStorage) and verify it's still a non-empty string before calling uploadPart.
  3. If uploadId is missing, start a fresh multipart upload (or use listParts to revalidate) instead of calling uploadPart.

Example fix

// before
const { uploadId } = await s3.createMultipartUpload({ key })
await s3.uploadPart({ key, uploadId: id /* typo: undefined */, partNumber: 1, body })
// after
await s3.uploadPart({ key, uploadId, partNumber: 1, body })
Defensive patterns

Strategy: validation

Validate before calling

if (typeof uploadId !== 'string' || !uploadId.trim()) {
  const created = await s3.createMultipartUpload({ key })
  uploadId = created.uploadId // start fresh session
}
await s3.uploadPart({ key, uploadId, partNumber, body })

Type guard

const hasUploadId = (v: unknown): v is string =>
  typeof v === 'string' && v.trim().length > 0

Prevention

When it happens

Trigger: Calling `s3.uploadPart({ key, uploadId: undefined, partNumber, body })` — typically because the createMultipartUpload result was not stored/propagated, or a resume flow loaded state where uploadId was lost; passing null or '' explicitly.

Common situations: Resuming uploads after a page reload where persisted state lost the uploadId; a typo destructuring `{ id }` instead of `{ uploadId }` from the create response; concurrent upload state overwritten by another file's session; retry logic that forgets to thread uploadId through.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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