Repository navigation
fix(skills): an unreadable skills dir must not abort the run (OPE-216) - #717
Open
devikaverma wants to merge 1 commit into
Open
devikaverma wants to merge 1 commit into
devikaverma wants to merge 1 commit into
Conversation
The live skill menu is rebuilt every turn (agent.py calls rescan() while assembling per-turn context), so every filesystem call in SkillLoader._discover sat on the hot path unguarded. pathlib ignores ENOENT/ENOTDIR/EBADF/ELOOP but propagates EACCES, so an unreadable <workspace>/.coworker/skills — an OPTIONAL dir, usually absent — raised straight out of the turn and terminated the run. Found while evaluating against benchmark datasets, where the agent runs headless as an unprivileged user: a root-owned .coworker/ appeared in the workspace mid-session and long runs died outright, several around 100 turns deep, after the work was already done. At startup the dir does not exist, ENOENT is ignored and the session begins normally, which is why it struck at arbitrary points rather than immediately. _discover now degrades to "no skills here" on OSError, and guards each skill's parse separately so one unreadable or malformed folder costs only that skill. Also drop "permission denied" from the provider no-access markers. Every OS PermissionError stringifies as "[Errno 13] Permission denied: <path>", so that substring turned any unreadable file into "Your account doesn't have access to <model>" — a billing failure that did not exist, and hours spent chasing a provider outage that never happened. Anthropic's genuine marker is the underscored error type permission_error, which was already listed and still matches. Three regression tests; all three fail without these changes.
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.
Two bugs found together while evaluating against benchmark datasets, with OpenWorker running
headless as an unprivileged user. The second made the first hard to find.
What
SkillLoader._discovermade its filesystem calls unguarded, and that scan is on the per-turnpath —
agent.py:663callsrescan()every turn to rebuild the live skill menu.pathlibignores ENOENT/ENOTDIR/EBADF/ELOOP but propagates EACCES, so an unreadable
<workspace>/.coworker/skills— optional and usually absent — raised straight out of the turnand ended the run. At startup the directory does not exist, ENOENT is ignored and the session
begins normally, which is why it struck at an arbitrary turn rather than at launch; long runs
died around 100 turns deep, after the work was already done.
The failure was then misreported.
_NO_ACCESSlisted"permission denied", matched againststr(exc).lower(), and every OSPermissionErrorstringifies as[Errno 13] Permission denied: <path>— so an unreadable file anywhere in a turn produced "Your account doesn't haveaccess to
<model>", a billing problem that did not exist, sending debugging after a provideroutage that never happened.
skills/base.py:_discoverdegrades to "no skills here" onOSError, and each skill'sparse is guarded separately so one unreadable or malformed folder costs only that skill
rather than the rest of the directory.
providers/errors.py: drop the"permission denied"marker. Anthropic's genuine marker isthe underscored type
permission_error, already listed and still matching; the OpenAImarkers are untouched. Unrecognised errors return
Noneso the caller surfaces the rawmessage.
classifier.
Testing
tests/test_skills.pyandtests/test_model_errors.py: 14 passed (3 new). All three newtests fail against unmodified main.
unmodified main (toolchain, tool-request, ui-refresh, gallery fixtures).
mkdir /src/.coworker && chmod 000): theunfixed build crashed and misreported it, the fixed build returned
skills=[]and classifiedthe error correctly.