s3.getObject.createReadStream How to catch the error?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
When streaming files from AWS S3 using s3.getObject().createReadStream() in Node.js, errors like missing keys, access denied, or network failures are not thrown as exceptions — they are emitted as events on the stream. If you do not listen for the error event, your application may crash with an unhandled error or silently fail.
The Problem
Fix 1: Listen for the Error Event
Fix 2: Use the Request's httpResponse Event
Catch HTTP-level errors before the stream starts flowing:
Fix 3: Promise-Based with Error Handling
Wrap the stream in a Promise for async/await:
Fix 4: Using AWS SDK v3 (Recommended)
The AWS SDK v3 uses a different pattern:
stream/promises.pipeline handles error propagation and cleanup automatically.
Piping to an Express Response
Common S3 Error Codes
| Error Code | HTTP Status | Meaning |
NoSuchKey | 404 | Object does not exist |
NoSuchBucket | 404 | Bucket does not exist |
AccessDenied | 403 | Missing permissions |
InvalidBucketName | 400 | Malformed bucket name |
RequestTimeout | 400 | Upload/download too slow |
SlowDown | 503 | Rate limit exceeded |
Common Pitfalls
- Unhandled error event: In Node.js, an
errorevent on a stream without a listener crashes the process. Always attach anerrorhandler before piping. - Partial file cleanup: If an error occurs mid-download, the destination file contains partial data. Delete it in the error handler.
- Concurrency and Throughput: When designing systems for high throughput, consider using multiple streams and instances for parallel processing.
- Transform Streams: For real-time data manipulation, integrate transform streams to process the data on the fly as it streams from S3.
- Retry Logic: Implement retry mechanisms for transient network issues. The AWS SDK v2 has built-in retry (
maxRetriesoption); SDK v3 uses@aws-sdk/middleware-retry. - Memory pressure: Do not buffer the entire S3 object in memory with
.promise()+Bodyfor large files. Use streaming.
Summary
- Always attach an
errorevent listener to S3createReadStream()before piping - Use
stream/promises.pipeline(Node 15+) or Promises to handle errors in async code - AWS SDK v3 provides a cleaner async pattern with
GetObjectCommand - Clean up partial files when download errors occur mid-stream
- Check if the object exists with
headObjectbefore streaming to HTTP responses
Related reading
- SageMaker and TensorFlow 2.0
- Same partition key's data distribution in DynamoDB
- Save AWS Cognito Users in DynamoDB
- Save Dataframe to csv directly to s3 Python
- Save sensitive data in React Native
- Scala actors receive vs react
- Samza/Kafka Failed to Update Metadata
- Sandbox bash72986 deny1 file-write-data /Users/XXX/ios/Pods/resources-to-copy-XXXShareExtension.txt

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.