{"record":{"id":"fca1cadbb7a5063f","repo":"overleaf/overleaf","slug":"error-reading-file-from-s3","errorCode":null,"errorMessage":"error reading file from S3","messagePattern":"error reading file from S3","errorType":"exception","errorClass":"ReadError","httpStatus":null,"severity":"error","filePath":"libraries/object-persistor/src/S3Persistor.js","lineNumber":251,"sourceCode":"    }\n    const observer = new PersistorHelper.ObserverStream({\n      metric: 's3.ingress', // ingress from S3 to us\n      bucket: bucketName,\n    })\n\n    const abortController = new AbortController()\n    let stream, contentEncoding\n    try {\n      const { Body, ContentEncoding } = await this._getClientForBucket(\n        bucketName\n      ).send(new GetObjectCommand(params), {\n        abortSignal: abortController.signal,\n      })\n      stream = Body\n      contentEncoding = ContentEncoding\n    } catch (err) {\n      abortController.abort()\n      throw PersistorHelper.wrapError(\n        err,\n        'error reading file from S3',\n        { bucketName, key, opts },\n        ReadError\n      )\n    }\n    // Return a PassThrough stream with a minimal interface. It will buffer until the caller starts reading. It will emit errors from the source stream (Stream.pipeline passes errors along).\n    const pass = new PassThrough()\n    const transformer = []\n    if (contentEncoding === 'gzip' && opts.autoGunzip) {\n      transformer.push(zlib.createGunzip())\n    }\n    // @ts-ignore stream (Body) can be undefined in GetObjectCommand\n    pipeline(stream, observer, ...transformer, pass, err => {\n      if (err) {\n        abortController.abort()\n      }\n    })","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/overleaf/overleaf/blob/28ad3b03b71cb4311decdcb55c36b33ec10d72db/libraries/object-persistor/src/S3Persistor.js#L233-L269","documentation":"Thrown by S3Persistor.getObjectStream when the GetObjectCommand fails (missing key, no read permission, or SDK/network error); the abort controller is triggered to cancel any partial transfer and the raw error is wrapped into a ReadError with bucket/key context.","triggerScenarios":"Thrown at libraries/object-persistor/src/S3Persistor.js:251 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Treat wrapped NotFoundError (S3 NoSuchKey) as a missing object: regenerate or re-upload it","Verify bucket read permissions and the exact key including prefixes","Check S3/network health and SDK credentials","Retry transient S3 5xx or timeout failures with backoff"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"28ad3b03b71cb4311decdcb55c36b33ec10d72db","analyzedAt":"2026-09-03T02:10:22.807Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T07:17:11.731Z"}