fix(agent_toolset): reject non-regular files in the write tool instead of hanging on a FIFO#1752
Open
roli-lpci wants to merge 1 commit into
Open
fix(agent_toolset): reject non-regular files in the write tool instead of hanging on a FIFO#1752roli-lpci wants to merge 1 commit into
write tool instead of hanging on a FIFO#1752roli-lpci wants to merge 1 commit into
Conversation
…d of hanging on a FIFO Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
beta_write_toolinsrc/anthropic/lib/tools/agent_toolset.pyhas no guard against the target path being aFIFO (or other non-regular file).
beta_read_toolandbeta_edit_toolbothstat()the target and rejectanything that isn't
S_ISREGbefore ever callingopen(), specifically because opening an unconnected FIFO forI/O blocks the calling thread indefinitely.
beta_edit_tool's guard is a direct copy ofbeta_read_tool's("Same guard as the read tool, edit reads the whole file too."), but
beta_write_toolnever received it.Since
write()'s file I/O runs directly in the coroutine (not offloaded to a worker thread), callingwriteon a path that resolves to a FIFO hangs the call forever and freezes the whole async event loop with it, not
just the one tool invocation. A directory at the same path does not trigger this:
write_text()on adirectory raises
IsADirectoryErrorimmediately, which the existingexcept OSErroralready converts to aclean
ToolError. A FIFO is the case that actually blocks instead of raising, and it's reachable any time anagent using this reference toolset is asked to write to a path that happens to be a named pipe, for example
one it created itself moments earlier with the
bashtool (mkfifo), or one already present in a shared /self-hosted environment.
Fix
stat()the target before opening it, same asread/edit, and reject non-regular files with aToolError.Unlike
read/edit,write's target commonly does not exist yet (a normal new-file write), so a missing fileis explicitly not an error here: only an existing non-regular file is rejected.
12 lines changed in
agent_toolset.py, all insidebeta_write_tool. No signature or return-type changes.Test
Added
test_write_rejects_fifo_instead_of_blockingtotests/lib/tools/test_agent_toolset.py, mirroring theexisting
test_read_rejects_directory/test_edit_rejects_directorypattern but using a realos.mkfifoFIFO(POSIX-only, skipped on Windows) since a directory doesn't reproduce this specific failure mode (it already
fails fast via
IsADirectoryError, only a FIFO blocks). The call runs on a background thread with a boundedjoin()so an unfixed SDK fails the test in ~5s instead of hanging the run:"write() hung opening a FIFO instead of rejecting it as a non-regular file"after a 5s bounded wait.ToolErrorcontaining"not a regular file".Full mapped test file (
tests/lib/tools/test_agent_toolset.py): 41 passed with the fix (the new test fails onthe unmodified baseline as above; the other 40 pass on both).
ruff checkandruff format --checkare cleanon both changed files.
Scope
This only touches
beta_write_tool. It does not changebeta_read_toolorbeta_edit_tool, and it does notmove the file I/O off the event loop thread (a separate, larger change if the maintainers want it); this PR is
scoped to closing the specific gap where
writeis the only one of the three file-mutating tools without thenon-regular-file guard the reference toolset's own docstring says the file tools provide ("the file tools ...
are safe to use without a sandbox").
Happy to extend the test to also cover a character device (e.g. skip on CI sandboxes without
/dev/nullwritable) if useful, but the FIFO case alone is a deterministic, cross-CI-safe repro of the hang.