transloadit/uppy · error · TypeError
[s3mini] partNumber must be a positive integer
Error message
[s3mini] partNumber must be a positive integer
What it means
A parameter guard inside _validateUploadPartParams, invoked by uploadPart, requiring `partNumber` to be a positive integer (1–10000 in S3 terms). Part numbers index parts within a multipart upload and S3 rejects zero, negatives, fractional values, and non-numbers at the protocol level; s3mini rejects them client-side with a TypeError.
Source
Thrown at packages/@uppy/aws-s3/src/s3-client/S3mini.ts:170
}
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) {
this._checkKey(key)
const { xhr, url } = await this.request({View on GitHub (pinned to 5d4dedd02a)
Solutions
- Use 1-based part numbers: `parts.map((chunk, i) => ({ partNumber: i + 1, body: chunk }))`.
- Coerce strings via Number.parseInt and validate: `const n = Number.parseInt(partNumber, 10); if (!Number.isInteger(n) || n < 1 || n > 10000) throw ...`.
Example fix
// before
chunks.forEach((chunk, i) => s3.uploadPart({ key, uploadId, partNumber: i, body: chunk }))
// after
chunks.forEach((chunk, i) => s3.uploadPart({ key, uploadId, partNumber: i + 1, body: chunk })) Defensive patterns
Strategy: validation
Validate before calling
const partNumber = Number.parseInt(rawPartNumber, 10)
if (!Number.isInteger(partNumber) || partNumber < 1 || partNumber > 10000) {
throw new RangeError(`Invalid partNumber: ${rawPartNumber}`)
} Type guard
const isValidPartNumber = (n: unknown): n is number => Number.isInteger(n) && n >= 1 && n <= 10000
Prevention
- Always derive part numbers as index + 1 in chunk loops.
- Never parse part numbers from strings without Number.parseInt validation.
When it happens
Trigger: Calling uploadPart with partNumber = 0 (e.g. from a 0-based loop index), a fractional number (1.5), a numeric string ('1'), NaN, or undefined.
Common situations: Using `array.forEach((chunk, i) => uploadPart({ partNumber: i, ... }))` with a 0-based index instead of i+1; parsing part numbers from strings and forgetting Number(); float math producing non-integers.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- [s3mini] key must be a non-empty string
- [s3mini] uploadId must be a non-empty string
- [s3mini] fileType must be a string
- [s3mini] Failed to create multipart upload: ${JSON.stringify
- [s3mini] Missing ETag in uploadPart response headers
AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28).
Data as JSON: /api/errors/1f06628f5609b9ce.
Report an issue: GitHub.