Repository navigation
fix(files): say "no such file or folder" when a download target is missing - #38
Merged
Merged
Conversation
…ssing Storage-transfer failures now return a typed executor.StorageError carrying only the HTTP status and the storage error <Code>, never the response body, so internal storage locations are no longer shown. Download maps a storage 404 to the existing NotFoundError. Upload uses the same error shape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Reviewed by Salty Hambot 🤖🧂 — rubric mode
Verdict: ✅ pass
| Dimension | Verdict | Notes |
|---|---|---|
| correctness | ✅ pass | newStorageError parses the XML Code safely, defaults empty on parse failure, and the 404→NotFoundError mapping in Download is wired correctly. |
| security | ✅ pass | The whole point of the PR: error bodies (which can reveal internal storage paths like org-42/user-7) are dropped, keeping only status and a regex-allowlisted code word. |
| privacy | ✅ pass | Storage location leakage in error messages is eliminated; tests assert org-ids and messages never surface. |
| reliability | ✅ pass | Body read is bounded by maxErrorBodyBytes via LimitReader; malformed XML falls back to status-only cleanly. |
| scalability | ✅ pass | No scaling concerns; error path reads at most 64KB of a small XML document. |
| observability | ✅ pass | Errors retain HTTP status and the storage code (NoSuchKey, AccessDenied), preserving enough signal to diagnose without leaking bodies. |
| clarity/maintainability | ✅ pass | Shared newStorageError dedups the upload/download error paths; comments explain the security intent clearly. |
| test quality | ✅ pass | Tests cover the AccessDenied/NoSuchKey cases, the no-leak assertions, non-word code rejection, and the Download 404→NotFoundError mapping — thorough for the changed behavior. |
Clean PR that yeets storage response bodies out the airlock — StorageError keeps only the status and an allowlisted , and the tests prove no org-id or key leaks through. Nothing to flag; both reviewers were right to stay quiet.
0 finding(s) posted.
💰 Review cost: $0.7576 · 173.6k in / 5.6k out tokens · ⏱️ 1m19.2s
💬 To request a re-review, comment @salty-hambot review
ClayMav
approved these changes
Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this delivers
wherobots files my-files cat|downloadof a missing file used to print S3's raw XML error (the API 307s to a presigned URL without checking existence, S3 answers 404, and the CLI passed the body through — exposing the internal key layout).no such file or folder: <path>error, the same as the API-404 path.<Code>element (validated before it is shown), via a newexecutor.StorageError.UploadFileToPresignedURL), whichjob-runs createalso uses: its storage failure message is now e.g.upload failed with HTTP 400 (InvalidRequest)rather than the raw body.Look hardest at
internal/executor/download.go—StorageError/newStorageErrorand the<Code>extraction.internal/files/ops.go— only a 404 becomesNotFoundError; other statuses keep thedownloading <path>: …wrapping.job-runs createshares it.Tests
Mock storage server returning 404
NoSuchKeyXML and a 403, both at the executor level and end-to-end throughfiles.Downloadwith a redirect; upload server-error test asserts the exact message and no body text.Left out
lsof a missing folder (still prints "No files or folders.") — out of scope, undecided.🤖 Generated with Claude Code