diff --git a/src/runtime/webcore/Blob.zig b/src/runtime/webcore/Blob.zig index 6cf5c0475545..4f9f8173887b 100644 --- a/src/runtime/webcore/Blob.zig +++ b/src/runtime/webcore/Blob.zig @@ -2975,7 +2975,19 @@ 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; + switch (stream_start) { + .FileSink => |*file_sink| { + file_sink.input_path.deinit(); + file_sink.input_path = input_path; + }, + .err => |err| { + sink.deref(); + return globalThis.throwValue(try err.toJS(globalThis)); + }, + else => { + 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..e09733a17c9b 100644 --- a/test/js/bun/util/filesink.test.ts +++ b/test/js/bun/util/filesink.test.ts @@ -268,3 +268,13 @@ it.skipIf(!isPosix)("does not leak native FileSink when a pending write fails (E // more than that indicates a native leak. expect(fileSinkInternals.liveCount()).toBeLessThanOrEqual(baseline + 1); }); + +it("writer() throws instead of crashing when options has a non-string path", () => { + const file = Bun.file(join(tmpdirSync(), "writer-invalid-path.txt")); + expect(() => file.writer({ path: Int32Array } as any)).toThrow(); +}); + +it("writer() throws instead of crashing when options has an invalid fd", () => { + const file = Bun.file(join(tmpdirSync(), "writer-invalid-fd.txt")); + expect(() => file.writer({ fd: "not-a-number" } as any)).toThrow(); +});