{"record":{"id":"e8ffdd287963ca44","repo":"transloadit/uppy","slug":"s3mini-filetype-must-be-a-string-e8ffdd","errorCode":null,"errorMessage":"[s3mini] fileType must be a string","messagePattern":"\\[s3mini\\] fileType must be a string","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/@uppy/aws-s3/src/s3-client/S3mini.ts","lineNumber":212,"sourceCode":"    })\n\n    return {\n      location: U.removeQueryString(url),\n      etag: U.sanitizeETag(xhr.getResponseHeader('etag')),\n      key,\n    }\n  }\n\n  /** Initiates a multipart upload and returns the upload ID. */\n  public override async createMultipartUpload({\n    key,\n    fileType = C.DEFAULT_STREAM_CONTENT_TYPE,\n    signal,\n  }: IT.CreateMultipartUploadParams) {\n    // todo support metadata here too?\n    this._checkKey(key)\n    if (typeof fileType !== 'string') {\n      throw new TypeError(`${C.ERROR_PREFIX}fileType must be a string`)\n    }\n\n    const { xhr } = await this.request({\n      request: { method: 'POST', key },\n      contentType: fileType,\n      signal,\n    })\n\n    const parsed = U.parseXml(xhr.responseText) as Record<string, unknown>\n\n    if (parsed && typeof parsed === 'object') {\n      // Check for both cases of InitiateMultipartUploadResult\n      const uploadResult =\n        (parsed.initiateMultipartUploadResult as Record<string, unknown>) ||\n        (parsed.InitiateMultipartUploadResult as Record<string, unknown>)\n\n      if (uploadResult && typeof uploadResult === 'object') {\n        // Check for both cases of uploadId","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/aws-s3/src/s3-client/S3mini.ts#L194-L230","documentation":"createMultipartUpload validates its `fileType` option (the Content-Type stored with the object) and throws a TypeError if it is not a string. The parameter defaults to a standard stream content type, so this only fires when an explicit non-string value (null, undefined passed explicitly overriding the default, number, object) is supplied.","triggerScenarios":"Calling createMultipartUpload({ key, fileType: file.type }) where file.type is undefined/'' is fine only when omitted; explicitly passing fileType: null, a number, or an object (e.g. the whole File instead of file.type) triggers it. Also passing fileType: undefined explicitly does NOT trigger it (default applies), so the real triggers are non-string truthy-or-null wrong types.","commonSituations":"Passing the File object itself instead of `file.type`; fileType sourced from a MIME lookup that returns false/null on unknown extensions; a config object where contentType field was renamed and is now undefined-overriding-default behavior after a version bump.","solutions":["Pass a string: `fileType: file.type || 'application/octet-stream'`.","If you don't know the type, omit the option entirely so the default content type applies.","Verify you're passing `file.type` (string), not `file` (File object) or a MIME-map lookup result that may be null."],"exampleFix":"// before\nawait s3.createMultipartUpload({ key, fileType: file }) // File object\n// after\nawait s3.createMultipartUpload({ key, fileType: file.type || 'application/octet-stream' })","handlingStrategy":"type-guard","validationCode":"const fileType = typeof file.type === 'string' && file.type ? file.type : 'application/octet-stream'","typeGuard":"const isFileType = (v: unknown): v is string => typeof v === 'string'","tryCatchPattern":null,"preventionTips":["Default MIME types with `file.type || 'application/octet-stream'` everywhere.","Pass file.type, never the File object, as fileType."],"tags":["aws-s3","multipart-upload","content-type","validation"],"backgroundTag":"invalid-argument-type","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}