Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/safe-bash/src/commands/network/output.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { readBytes, writeBytes, type ByteSource, type CommandContext } from "../../contracts/index.js";
import { FsError, readBytes, writeBytes, type ByteSource, type CommandContext } from "../../contracts/index.js";
import { openFileOutput } from "../../contracts/filesystem-output.js";
import { outputFailure } from "../../contracts/io.js";
import { pathOf } from "../internal.js";
Expand Down Expand Up @@ -42,7 +42,7 @@ export async function writeOutput(context: CommandContext, path: string | undefi
} catch (error) {
signal.throwIfAborted();
if (error instanceof CurlError) throw error;
throw new CurlError(23, "Failed writing virtual output file");
throw new CurlError(23, error instanceof FsError ? `Failed writing virtual output file: ${error.message}` : "Failed writing virtual output file");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ for (const stage of ["before", "acquired", "consumed"] as const) {
});
}

for (const failure of [new FsError("EACCES"), new FsError("EROFS"), new FsError("EIO"), { code: "ENOTSUP" }]) {
for (const failure of [new FsError("EACCES"), new FsError("EROFS"), new FsError("EIO"), new FsError("EACCES", { path: "/out", message: "This loaded file is read-only. Write to a new path instead.", cause: new Error("private backend detail") }), { code: "ENOTSUP" }, Object.assign(new Error("private backend detail"), { code: "EACCES" })]) {
test(`curl preserves stream failure without replay: ${failure.code}`, async () => {
const backing = createMemoryFileSystem();
const fs: FileSystem = { ...buffered(backing), capabilities: {} };
Expand All @@ -105,7 +105,10 @@ for (const failure of [new FsError("EACCES"), new FsError("EROFS"), new FsError(
try {
const result = await shell.exec("curl https://example.invalid/file -o /out");
assert.equal(result.exitCode, 23);
assert.equal(result.stderr, "curl: (23) Failed writing virtual output file\n");
assert.equal(result.stderr, failure instanceof FsError
? `curl: (23) Failed writing virtual output file: ${failure.message}\n`
: "curl: (23) Failed writing virtual output file\n");
assert.doesNotMatch(result.stderr, /private backend detail/u);
assert.equal(writes, 0);
assert.equal(produced, 0);
await assert.rejects(backing.readFile("/out"), { code: "ENOENT" });
Expand Down Expand Up @@ -221,7 +224,7 @@ test("curl does not retry failed buffered appends after a partial mounted write"
try {
const result = await shell.exec("curl https://example.invalid/file -o /scratch/out");
assert.equal(result.exitCode, 23);
assert.equal(result.stderr, "curl: (23) Failed writing virtual output file\n");
assert.equal(result.stderr, "curl: (23) Failed writing virtual output file: EIO: input/output error, appendFile '/scratch/out'\n");
assert.equal(appended, 2);
assert.equal(produced, 2);
assert.deepEqual(await backing.readFile("/out"), new Uint8Array([1]));
Expand Down
Loading