Description
The SDK should raise specific, semantically meaningful exception subclasses (e.g. DaytonaNotFoundError, DaytonaAuthenticationError) instead of the generic DaytonaError for distinct failure modes. This lets consumers use idiomatic try/except patterns instead of string-parsing error messages.
Problem
Today the SDK inconsistently raises the base DaytonaError for situations where a more specific subclass already exists or should exist. For example, calling sandbox.fs.download_file() on a path that doesn't exist sometimes raises DaytonaNotFoundError and sometimes raises the base DaytonaError with a message containing "file not found."
This forces consumers to write brittle workarounds like:
try:
data = await sandbox.fs.download_file(path)
except DaytonaNotFoundError:
return {}
except DaytonaError as exc:
# SDK sometimes raises the base class instead of DaytonaNotFoundError
if "file not found" in str(exc).lower():
return {}
raise
The string-matching fallback is fragile — it breaks if the server-side message changes wording, is localized, or includes additional context. Idiomatic Python expects distinct exception types for distinct failure categories.
Proposal
Audit every code path in the SDK that raises DaytonaError and map each to a specific subclass. Where a subclass doesn't exist yet, create one.
Suggested exception hierarchy:
DaytonaError (base — keep as the catch-all parent)
├── DaytonaNotFoundError # 404 / resource doesn't exist
├── DaytonaAuthenticationError # 401 / invalid or missing API key
├── DaytonaAuthorizationError # 403 / insufficient permissions
├── DaytonaRateLimitError # 429 / rate limit exceeded
├── DaytonaConflictError # 409 / resource already exists or state conflict
├── DaytonaValidationError # 400 / bad input, malformed request
├── DaytonaTimeoutError # request or operation timed out
└── DaytonaConnectionError # network-level failure (DNS, TLS, etc.)
DX & UX Implementation:
- Interface: No CLI changes. SDK consumers switch from string-matching
except DaytonaError blocks to specific except DaytonaNotFoundError blocks. Existing except DaytonaError catch-alls continue to work since all subclasses inherit from it — this is fully backward-compatible.
- Feedback: Each exception should carry structured attributes (
status_code, error_code, message) so consumers can programmatically react without parsing strings. Example:
except DaytonaNotFoundError as exc:
print(exc.status_code) # 404
print(exc.error_code) # "FILE_NOT_FOUND"
print(exc.message) # "File '/workspace/manifest.json' does not exist"
- Configuration: No configuration changes needed.
Consistency across SDKs: If the TypeScript SDK has the same issue, the same hierarchy and error codes should be adopted there to keep the multi-language experience consistent.
Acceptance Criteria
Impact
Eliminates a class of fragile string-parsing workarounds across every codebase that uses the Daytona SDK. Consumers get idiomatic, reliable error handling that won't break when message text changes. This is a foundational DX improvement — predictable exceptions are table stakes for a production-grade SDK.
Description
The SDK should raise specific, semantically meaningful exception subclasses (e.g.
DaytonaNotFoundError,DaytonaAuthenticationError) instead of the genericDaytonaErrorfor distinct failure modes. This lets consumers use idiomatictry/exceptpatterns instead of string-parsing error messages.Problem
Today the SDK inconsistently raises the base
DaytonaErrorfor situations where a more specific subclass already exists or should exist. For example, callingsandbox.fs.download_file()on a path that doesn't exist sometimes raisesDaytonaNotFoundErrorand sometimes raises the baseDaytonaErrorwith a message containing "file not found."This forces consumers to write brittle workarounds like:
The string-matching fallback is fragile — it breaks if the server-side message changes wording, is localized, or includes additional context. Idiomatic Python expects distinct exception types for distinct failure categories.
Proposal
Audit every code path in the SDK that raises
DaytonaErrorand map each to a specific subclass. Where a subclass doesn't exist yet, create one.Suggested exception hierarchy:
DX & UX Implementation:
except DaytonaErrorblocks to specificexcept DaytonaNotFoundErrorblocks. Existingexcept DaytonaErrorcatch-alls continue to work since all subclasses inherit from it — this is fully backward-compatible.status_code,error_code,message) so consumers can programmatically react without parsing strings. Example:Consistency across SDKs: If the TypeScript SDK has the same issue, the same hierarchy and error codes should be adopted there to keep the multi-language experience consistent.
Acceptance Criteria
download_file,upload_file,list_dir, etc.) raiseDaytonaNotFoundError— not the baseDaytonaError— when a path doesn't existDaytonaAuthenticationError(related: API should return Unauthorized for wrong API keys #1772)DaytonaError(backward-compatible)status_code,error_code,message)except DaytonaErrorblocks in consumer code continue to work without changesImpact
Eliminates a class of fragile string-parsing workarounds across every codebase that uses the Daytona SDK. Consumers get idiomatic, reliable error handling that won't break when message text changes. This is a foundational DX improvement — predictable exceptions are table stakes for a production-grade SDK.