{"record":{"id":"147730cc4fddd01f","repo":"transloadit/uppy","slug":"file-data-is-missing-for-file-options-file-id","errorCode":null,"errorMessage":"File data is missing for file ${options.file.id}","messagePattern":"File data is missing for file (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@uppy/aws-s3/src/S3Uploader.ts","lineNumber":86,"sourceCode":"  etag?: string\n}\n\nexport default class S3Uploader<M extends Meta, B extends Body> {\n  readonly #data: NonNullable<LocalUppyFile<M, B>['data']>\n  #key: string | undefined\n  readonly #options: S3UploaderOptions<M, B>\n  readonly #eventManager: EventManager<M, B>\n\n  #chunks: Chunk[] = []\n  #chunkState: ChunkState[] = []\n  #shouldUseMultipart: boolean = false\n  #uploadId?: string\n  #uploadHasStarted: boolean = false\n  #abortController: AbortController | undefined\n\n  constructor(options: S3UploaderOptions<M, B>) {\n    if (options.file.data == null) {\n      throw new Error(`File data is missing for file ${options.file.id}`)\n    }\n    this.#options = options\n    this.#data = options.file.data\n    this.#eventManager = new EventManager(options.uppy)\n\n    // Detect resume state from file (persisted by Golden Retriever across page refreshes).\n    // Must run before #initChunks so it can force multipart mode for resumed uploads.\n    const resumeState = options.file.s3Multipart\n    if (resumeState) {\n      this.#key = resumeState.key\n      this.#uploadId = resumeState.uploadId\n      this.#uploadHasStarted = true\n    }\n\n    const fileSize = options.file.data.size\n\n    // Determine if we should use multipart\n    // If we're resuming a multipart upload, force multipart. Otherwise use","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/aws-s3/src/S3Uploader.ts#L68-L104","documentation":"This is Companion's top-level Express error handler in packages/@uppy/companion/src/standalone/index.ts. When NODE_ENV is production, it masks the underlying error details and returns a generic 500 with only a requestId, to avoid leaking internal error messages or stack traces to clients. The real cause is logged server-side via logger.error(err, 'root.error', req.id).","triggerScenarios":"Any unhandled exception thrown in a route handler, middleware, or provider call that propagates to the Express error handler while NODE_ENV=production (e.g. an upstream provider API failure, a malformed request that crashes parsing, or a bug in a custom provider).","commonSituations":"Developers see only 'Something went wrong' and cannot reproduce locally where NODE_ENV is development (which returns error.message). Common causes: Companion misconfiguration, an expired/invalid provider token causing an exception mid-request, or network failures to the provider's API.","solutions":["Check the Companion server logs for the 'root.error' entry (keyed by the returned requestId) to see the actual stack trace","Reproduce locally with NODE_ENV=development to get error.message and err in the response body","Verify provider credentials (key/secret) and that the provider's API is reachable from the Companion host","If the error comes from a custom provider, wrap its network calls and validate responses before use"],"exampleFix":"// before (unclear root cause)\nres.status(500).json({ message: 'Something went wrong', requestId: req.id })\n\n// after: inspect via logs\nlogger.error(err, 'root.error', req.id) // then grep server logs for requestId returned to the client","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// wrap Companion HTTP calls client-side\ntry {\n  await fetch(companionUrl + path, opts)\n} catch (err) {\n  // surface requestId to the user; correlate with server logs\n  reportToOps(responseBody.requestId)\n  throw new RetryableError('companion unavailable')\n}","preventionTips":["Always capture the requestId from 500 responses and include it in bug reports","Run Companion with structured logging so root.error entries are searchable by requestId","Keep NODE_ENV=development in staging to get detailed errors while never exposing them in production"],"tags":["companion","http-500","error-handler","production"],"backgroundTag":"internal-server-error","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}