Repository navigation
Description
Introduce a machine-readable, domain-level error taxonomy in a new apify.errors module. This is a low-risk, additive change with high leverage for machine-driven (agent) use.
It builds on apify-client-python#423: the client already exposes typed, HTTP-status-based exceptions (ApifyApiError + UnauthorizedError, ForbiddenError, NotFoundError, RateLimitError, ServerError, …). This issue adds the next layer up — Actor-run-aware errors with a .retryable flag — and maps the client's exceptions into it at the SDK boundary.
Problem
The SDK itself defines zero custom exceptions. Failures surface as generic builtins (RuntimeError, ValueError) or as raw apify_client errors. An autonomous agent can't branch on those to decide retry vs. reformulate input vs. pick another tool vs. give up. That needs typed, coded, .retryable-tagged errors with Actor-run semantics (a 429 is transient; a FAILED run with a bad input is not).
Proposed design
ApifyError(Exception) with code: str and retryable: bool, plus typed subclasses:
class ApifyError(Exception):
code: str
retryable: bool
class ActorRunError(ApifyError):
def __init__(self, run: Run): ... # .run_id .status .exit_code .status_message
class InputValidationError(ApifyError, ValueError): ... # still caught by `except ValueError`
class ChargeLimitExceededError(ApifyError): ...
class RateLimitError(ApifyError): retryable = True
class AuthenticationError(ApifyError): ...
class ActorTimeoutError(ApifyError): retryable = TrueExport the names additively from apify/__init__.py.
Mapping apify_client → apify.errors
Translate the client's exceptions at the SDK boundary (the client's RateLimitError / UnauthorizedError names overlap, so the mapping must be explicit):
apify_client.errors |
apify.errors |
|---|---|
UnauthorizedError (401), ForbiddenError (403) |
AuthenticationError |
RateLimitError (429) |
RateLimitError (retryable=True) |
ServerError (5xx) |
ApifyError (retryable=True) |
InvalidRequestError (400) |
InputValidationError / ApifyError |
other ApifyApiError |
ApifyError |
ActorRunError, ChargeLimitExceededError, and ActorTimeoutError are derived from run status / exit code, not from HTTP errors.
Acceptance criteria
-
apify.errorsmodule withApifyError(code, retryable)and the subclasses above. -
apify_clientexceptions mapped to the appropriate typed error at the SDK boundary. - Names exported additively from
apify/__init__.py. - No existing method changes what it raises;
except ValueErrorstill catchesInputValidationError.
Risk: Medium. New exceptions appear only on new code paths (opt-in raise_on_failure); existing methods keep raising RuntimeError / ValueError.
Activity
[-]apify.errors: machine-readable error taxonomy (ApifyError + typed subclasses)[/-][+]Add apify.errors: machine-readable error taxonomy[/+][-]Add apify.errors: machine-readable error taxonomy[/-][+]Add apify.errors: domain-level error taxonomy over apify-client exceptions[/+]