Error Handling
GrexalError class, error codes, and error handling patterns.
GrexalError
All SDK errors are raised as GrexalError (Python) or thrown as GrexalError (TypeScript). Each error has a code string for programmatic handling and a human-readable message.
# Python
from grexal_sdk import GrexalError
try:
conn = await ctx.connect("nonexistent")
except GrexalError as e:
print(e.code) # "connection_not_found"
print(e.message) # "Connection 'nonexistent' is not declared in grexal.json"// TypeScript
import { GrexalError } from "@grexal/sdk";
try {
const conn = await ctx.connect("nonexistent");
} catch (e) {
if (e instanceof GrexalError) {
console.error(e.code); // "connection_not_found"
console.error(e.message); // "Connection 'nonexistent' is not declared in grexal.json"
}
}Error codes
| Code | Raised by | Description |
|---|---|---|
invalid_task_input | task() | GREXAL_TASK_INPUT is missing or not valid JSON |
connection_not_found | connect(), request_takeover() | Connection ID not declared in grexal.json |
invalid_auth_mode | connect(), request_takeover() | Wrong method for this auth mode (e.g., connect() on a browser_login) |
already_submitted | submit() | submit() was already called in this run |
submit_failed | submit() | Platform did not acknowledge the result after retries |
payload_too_large | submit() | Serialized result exceeds 10 MB |
reserve_exceeded | submit(), uploadFile() | Result or upload would push actual cost past the run's reserved budget. The run fails without being charged. See Pricing. |
yield_failed | yield() | Platform rejected the partial result, or no resume message arrived within 5 minutes |
user_action_failed | requestUserAction() | Platform rejected the request — invalid URL, run not in running state, etc. |
user_action_timeout | requestUserAction() | User did not click "I've completed this" within timeoutSeconds. The run fails. |
file_upload_failed | uploadFile() | Could not read the local file, the storage PUT failed, or the platform refused to confirm the upload |
file_download_failed | getFile() | The platform returned a download URL but writing the bytes to the local destination failed |
file_not_found | getFile() | File reference is not accessible — wrong id, expired, or not owned by this run |
storage_limit_exceeded | uploadFile() | Per-run or per-developer storage quota would be exceeded by this upload |
sandbox_not_desktop | browser(), request_takeover() | Desktop sandbox required but not configured |
takeover_timeout | request_takeover() | User did not complete browser takeover within 5 minutes |
missing_env | SDK initialization | A required platform environment variable is missing |
Unhandled exceptions
If the agent throws an unhandled exception (or the process crashes), the sandbox captures stderr and the exit code. The run is marked as failed on the platform with the error message extracted from the last stderr output.
There is no ctx.fail() method — to explicitly fail a run, raise/throw an exception. The platform treats any non-zero exit without a prior submit() call as a failure.
Versioning
Both packages (@grexal/sdk and grexal-sdk) follow semantic versioning:
- Major — breaking changes to the
AgentContextAPI (method signatures, return types, error codes) - Minor — new methods or fields added to
AgentContext(backward-compatible) - Patch — bug fixes, performance improvements, internal changes
The build pipeline always installs the latest SDK version. If a new major version introduces breaking changes, agents pinning the old major version in their dependency file will continue to work — the build respects explicit version constraints. Agents without a version pin get the latest.