crewAIInc/crewAI · error · ValueError
Unknown action: {action}
Error message
Unknown action: {action} What it means
Raised by E2BFileTool._run when the 'action' string does not match any of the handled cases (read, write, append, list, delete, mkdir, info, exists). It is the final else-branch after the if/elif chain over known actions, so any typo'd or unsupported action name reaches it.
Source
Thrown at lib/crewai-tools/src/crewai_tools/tools/e2b_sandbox_tool/e2b_file_tool.py:117
if action == "read":
return self._read(sandbox, path, binary=binary)
if action == "write":
return self._write(sandbox, path, content or "", binary=binary)
if action == "append":
return self._append(sandbox, path, content or "", binary=binary)
if action == "list":
return self._list(sandbox, path, depth=depth)
if action == "delete":
sandbox.files.remove(path)
return {"status": "deleted", "path": path}
if action == "mkdir":
created = sandbox.files.make_dir(path)
return {"status": "created", "path": path, "created": bool(created)}
if action == "info":
return self._info(sandbox, path)
if action == "exists":
return {"path": path, "exists": bool(sandbox.files.exists(path))}
raise ValueError(f"Unknown action: {action}")
finally:
self._release_sandbox(sandbox, should_kill)
def _read(self, sandbox: Any, path: str, *, binary: bool) -> dict[str, Any]:
if binary:
data: bytes = sandbox.files.read(path, format="bytes")
return {
"path": path,
"encoding": "base64",
"content": base64.b64encode(data).decode("ascii"),
}
try:
content: str = sandbox.files.read(path)
return {"path": path, "encoding": "utf-8", "content": content}
except UnicodeDecodeError:
data = sandbox.files.read(path, format="bytes")
return {
"path": path,View on GitHub (pinned to 754d7323be)
Solutions
- Use one of the supported actions exactly: 'read', 'write', 'append', 'list', 'delete', 'mkdir', 'info', 'exists' (check the schema description for the canonical list).
- If you need 'remove', the supported equivalent is action='delete'.
- Validate the action string in your own code before invoking the tool (see defense below).
Example fix
# before tool._run(action='remove', path='/tmp/x.txt') # after tool._run(action='delete', path='/tmp/x.txt')
Defensive patterns
Strategy: validation
Validate before calling
E2B_FILE_ACTIONS = {'read','write','append','list','delete','mkdir','info','exists'}
assert action in E2B_FILE_ACTIONS, f'action must be one of {sorted(E2B_FILE_ACTIONS)}' Type guard
def is_e2b_file_action(a: str) -> bool:
return a in {'read','write','append','list','delete','mkdir','info','exists'} Try / catch
try:
result = tool._run(action=action, path=path)
except ValueError as e:
if 'Unknown action' in str(e):
action = 'delete' if action == 'remove' else action # map or re-raise
else:
raise Prevention
- Keep the supported action set in one constant shared with your agent's prompt.
- Tell the LLM the exact enum of actions in the task description.
When it happens
Trigger: Passing action='remove' or action='copy' (not supported), a typo like action='lst' or 'Write', or a differently-cased action such as 'READ' — matching is case-sensitive exact string comparison.
Common situations: An LLM agent invents an action not in the tool's description; callers upgraded from an older version where action names differed; locale/case confusion in generated tool args.
Related errors
- action='append' requires 'content'. Pass the chunk to append
- Project name '{name}' would generate folder name '{folder_na
- Project name '{name}' contains no valid characters for a Pyt
- Project name '{name}' would generate class name '{class_name
- Project name '{name}' would generate class name '{class_name
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/aeed95d2f2d96ac2.
Report an issue: GitHub.