@@ -183,14 +183,35 @@ export default class GitHubStream extends GitHubBase {
183183 const stream1 = content . pipe ( new stream . PassThrough ( ) ) ;
184184 const stream2 = content . pipe ( new stream . PassThrough ( ) ) ;
185185
186+ // Safety net: guarantee an `error` listener exists on both branches
187+ // before any error can be emitted. storage.write attaches its listener
188+ // only after an `await mk(...)`, and the route handler attaches its
189+ // listener after awaiting this function — both leave a window where
190+ // an upstream error would have no listener and escalate to
191+ // uncaughtException, crashing the streamer.
192+ const noop = ( ) => { } ;
193+ stream1 . on ( "error" , noop ) ;
194+ stream2 . on ( "error" , noop ) ;
195+
186196 content . on ( "error" , ( error ) => {
187- error = new AnonymousError ( "file_not_found" , {
188- httpStatus : ( error as { status ?: number ; httpStatus ?: number } ) . status || ( error as { httpStatus ?: number } ) . httpStatus ,
197+ const httpStatus =
198+ ( error as { response ?: { statusCode ?: number } } ) ?. response
199+ ?. statusCode ??
200+ ( error as { status ?: number } ) ?. status ??
201+ ( error as { httpStatus ?: number } ) ?. httpStatus ;
202+ const code =
203+ httpStatus === 422
204+ ? "file_too_big"
205+ : httpStatus === 403
206+ ? "file_not_accessible"
207+ : "file_not_found" ;
208+ const wrapped = new AnonymousError ( code , {
209+ httpStatus,
189210 cause : error as Error ,
190211 object : filePath ,
191212 } ) ;
192- stream1 . emit ( "error" , error ) ;
193- stream2 . emit ( "error" , error ) ;
213+ stream1 . destroy ( wrapped ) ;
214+ stream2 . destroy ( wrapped ) ;
194215 } ) ;
195216
196217 storage . write ( repoId , filePath , stream1 , this . type ) ;
0 commit comments