Repository navigation
Description
Context
PR #357 split three of CloudKit's 14 documented `serverErrorCode` values into dedicated `CloudKitError` cases:
- `.quotaExceeded(reason:, hint: QuotaHint?)` — 413 / `QUOTA_EXCEEDED`
- `.badRequest(reason:)` — 400 / `BAD_REQUEST`
- `.atomicFailure(reason:)` — 400 / `ATOMIC_ERROR`
Those three got promoted because they were either a) heavily overloaded at the wire level (`QUOTA_EXCEEDED` carries storage-quota, per-record size, and per-asset size) or b) semantically distinct from each other despite sharing an HTTP status (`BAD_REQUEST` vs `ATOMIC_ERROR`). The remaining 11 server codes still land in `.httpErrorWithDetails(statusCode:, serverErrorCode:, reason:)` with consumers needing string matching.
Proposed work
Enumerate the rest of the documented `serverErrorCode` values as dedicated cases so consumers can pattern-match by intent, and add an `.unknownServerError(code: String, statusCode: Int, reason: String?)` fallback so forward-compat is preserved when Apple adds new codes.
Codes to enumerate (from `openapi.yaml` `serverErrorCode` enum):
| Code | HTTP | Suggested case |
|---|---|---|
| `ACCESS_DENIED` | 403 | `.accessDenied(reason:)` |
| `AUTHENTICATION_FAILED` | 401 | `.authenticationFailed(reason:)` |
| `AUTHENTICATION_REQUIRED` | 421 | `.authenticationRequired(reason:)` |
| `CONFLICT` | 409 | `.conflict(reason:)` |
| `EXISTS` | 409 | `.exists(reason:)` |
| `INTERNAL_ERROR` | 500 | `.internalServerError(reason:)` |
| `NOT_FOUND` | 404 | `.notFound(reason:)` |
| `THROTTLED` | 429 | `.throttled(reason:)` |
| `TRY_AGAIN_LATER` | 503 | `.tryAgainLater(reason:)` |
| `VALIDATING_REFERENCE_ERROR` | 412 | `.validatingReferenceError(reason:)` |
| `ZONE_NOT_FOUND` | 404 | `.zoneNotFound(reason:)` |
Plus `.unknownServerError(code: String, statusCode: Int, reason: String?)` for codes Apple may add in future spec revisions.
Why this is post-1.0 rather than blocking beta.2
This is a breaking API change that touches:
- `CloudKitError` enum (add 11 cases, change `httpErrorWithDetails` semantics)
- `ResponseProcessor` / `CloudKitError+OpenAPI.swift` (dispatch by code)
- Every consumer that pattern-matches `.httpErrorWithDetails(_, "
", _)` - Every test that asserts on those patterns
PR #357 took the narrowly-scoped path: split only the three codes where there's either disambiguation value (`QUOTA_EXCEEDED` + `QuotaHint`) or semantic distinction (`ATOMIC_ERROR`). The remaining 11 don't have hint vocabularies and the action a consumer takes on them is roughly uniform (re-auth, back off, retry, surface) so the marginal value of splitting is lower.
Splitting them anyway gives type-safe matching and avoids "what's the current set of codes?" being a string-comparison concern. But it's API churn that doesn't need to land before beta.2.
Verification
- All existing `.httpErrorWithDetails(...)` pattern-match sites must be migrated to the new cases or to `.unknownServerError`.
- `MockTransport`-based tests should cover each code's roundtrip through the factory.
- The `.unknownServerError` path should be exercised with a mock returning a code not in the enum (forward-compat smoke test).
Related: closed sibling work in #356 (pre-1.0 hardening umbrella). Not adding this as a sub-issue of #356 since #356 is for pre-1.0 work; this is post-1.0.
🤖 Generated with Claude Code
Activity
leogdion commentedon Aug 20, 2026
Moving from the v1.0.0-beta.3 milestone to v1.0.0-beta.4 — work not yet complete.
Refactor CloudKitError to per-serverErrorCode cases (#358)
Merge #358: per-serverErrorCode CloudKitError cases
Migrate #358's new tests off the query overload removed by #421
Refactor CloudKitError to per-serverErrorCode cases (#358)
Migrate #358's new tests off the query overload removed by #421
Refactor CloudKitError to per-serverErrorCode cases (#358)
Migrate #358's new tests off the query overload removed by #421
Refactor CloudKitError to per-serverErrorCode cases (#358)
Migrate #358's new tests off the query overload removed by #421
Remove deprecated API, model server error codes, refactor FieldValue …
leogdion commentedon Aug 28, 2026
Resolved on
v1.0.0-beta.4via #424 (commit 1411227). 14 documentedserverErrorCodevalues now have dedicatedCloudKitErrorcases with.unknownServerErrorfallback (CloudKitError+ServerErrorCode.swift).Remove deprecated API, model server error codes, refactor FieldValue …
v1.0.0 beta.4 (#439)