diff --git a/src/runtime/webcore/Blob.zig b/src/runtime/webcore/Blob.zig index 6cf5c0475545..344984fdfaff 100644 --- a/src/runtime/webcore/Blob.zig +++ b/src/runtime/webcore/Blob.zig @@ -2975,7 +2975,13 @@ pub fn getWriter( if (arguments.len > 0 and arguments.ptr[0].isObject()) { stream_start = try jsc.WebCore.streams.Start.fromJSWithTag(globalThis, arguments[0], .FileSink); - stream_start.FileSink.input_path = input_path; + if (stream_start == .err) { + sink.deref(); + return globalThis.throwValue(try stream_start.err.toJS(globalThis)); + } + if (stream_start == .FileSink) { + stream_start.FileSink.input_path = input_path; + } } switch (sink.start(stream_start)) { diff --git a/test/js/bun/util/filesink.test.ts b/test/js/bun/util/filesink.test.ts index 736e5b085731..df1ff5cbd8f2 100644 --- a/test/js/bun/util/filesink.test.ts +++ b/test/js/bun/util/filesink.test.ts @@ -219,6 +219,13 @@ if (isWindows) { }); } +it.skipIf(isWindows)("writer() with invalid path/fd options throws instead of crashing", () => { + const file = path.join(tmpdirSync(), "test.txt"); + expect(() => Bun.file(file).writer({ path: 123 })).toThrow(expect.objectContaining({ code: "EINVAL" })); + expect(() => Bun.file(file).writer({ fd: "hello" })).toThrow(expect.objectContaining({ code: "EBADF" })); + expect(() => Bun.file(file).writer({ fd: 2 ** 53 })).toThrow(expect.objectContaining({ code: "EBADF" })); +}); + // When a write to a pollable fd returns `.pending`, FileSink takes a // `must_be_kept_alive_until_eof` ref on itself so it survives until the // buffered data is drained. If the write later fails (e.g. EPIPE because the