{"record":{"id":"25cdc9336ce7942a","repo":"transloadit/uppy","slug":"s3mini-key-must-be-a-non-empty-string","errorCode":null,"errorMessage":"[s3mini] key must be a non-empty string","messagePattern":"\\[s3mini\\] key must be a non-empty string","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/@uppy/aws-s3/src/s3-client/S3mini.ts","lineNumber":156,"sourceCode":"      new URL(candidate)\n\n      // Find the last non-slash character\n      let endIndex = candidate.length\n      while (endIndex > 0 && candidate[endIndex - 1] === '/') {\n        endIndex--\n      }\n      return endIndex === candidate.length\n        ? candidate\n        : candidate.substring(0, endIndex)\n    } catch {\n      const msg = `${C.ERROR_ENDPOINT_FORMAT} But provided: \"${raw}\"`\n      throw new TypeError(msg)\n    }\n  }\n\n  private _checkKey(key: string): void {\n    if (typeof key !== 'string' || key.trim().length === 0) {\n      throw new TypeError(C.ERROR_KEY_REQUIRED)\n    }\n  }\n\n  private _validateUploadPartParams(\n    key: string,\n    uploadId: string,\n    partNumber: number,\n  ): void {\n    this._checkKey(key)\n    if (typeof uploadId !== 'string' || uploadId.trim().length === 0) {\n      throw new TypeError(C.ERROR_UPLOAD_ID_REQUIRED)\n    }\n    if (!Number.isInteger(partNumber) || partNumber <= 0) {\n      throw new TypeError(\n        `${C.ERROR_PREFIX}partNumber must be a positive integer`,\n      )\n    }\n  }","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/aws-s3/src/s3-client/S3mini.ts#L138-L174","documentation":"A guard in s3mini that requires the object `key` to be a non-empty, non-whitespace string. Every object-level operation (putObject, createMultipartUpload, listParts, abortMultipartUpload, uploadPart validation) calls _checkKey before making a request, because S3 needs a valid object key to build the request path. It throws a TypeError when the key is missing, not a string, or blank.","triggerScenarios":"Calling putObject({ key: '' }) or createMultipartUpload({ key: undefined }); passing a key of only spaces; key computed from a filename that is undefined (e.g. `file.meta.key` that was never set); passing a Buffer or object as key.","commonSituations":"Uppy/AWS S3 uploader generating the key from file metadata where the field is absent; renaming/refactoring key-generation code so it returns undefined; user uploads where the filename is empty and the key template produces a blank string.","solutions":["Ensure the key passed to the S3 call is a non-empty string, e.g. derive it deterministically: `key = \\`${folder}/${file.name}\\`` and fall back to a generated name if `file.name` is empty.","If the key comes from user input or metadata, validate/trim it before calling the API.","Check that you're not passing the key under a different option name (e.g. `path`, `name`) than the API expects."],"exampleFix":"// before\nawait s3.createMultipartUpload({ key: file.meta.key }) // undefined\n// after\nconst key = file.meta.key ?? `uploads/${crypto.randomUUID()}-${file.name}`\nawait s3.createMultipartUpload({ key })","handlingStrategy":"type-guard","validationCode":"const key = typeof file.key === 'string' && file.key.trim() ? file.key : `uploads/${crypto.randomUUID()}-${file.name}`","typeGuard":"const isValidKey = (k: unknown): k is string =>\n  typeof k === 'string' && k.trim().length > 0","tryCatchPattern":"try { await s3.putObject({ key, body }) } catch (e) { if (e instanceof TypeError && /non-empty string/.test(e.message)) {/* regenerate key and retry */} else throw e }","preventionTips":["Derive keys from a single key-generation function with a non-empty fallback.","Type your upload params (CreateMultipartUploadParams) so TS catches undefined keys at compile time."],"tags":["aws-s3","validation","object-key","multipart-upload"],"backgroundTag":"missing-required-parameter","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}