Problem
Generated client calls currently wrap response decoding failures in ClientError, which gives useful context like operation ID, request, response, response body, cause, and the underlying decoding error.
However, adopters do not have a central place to observe those decoding failures.
In production, this makes it hard to report response decoding problems consistently without wrapping every generated client call manually.
do {
let output = try await client.getUser(.init(path: .init(id: id)))
// use output
} catch {
errorReporter.record(error)
throw error
}
This works, but it is easy to miss call sites and it repeats the same reporting code across the app.
Middleware is useful for HTTP-level logging, but it observes the request/response around the transport call. The decoding failure happens later, when the runtime decodes the response body into the generated output type.
Proposed direction
Add a small callback on Configuration for response decoding failures:
public var clientResponseDecodingErrorHandler: (@Sendable (ClientError) -> Void)?
The callback would be called when response decoding fails, after the failure has been wrapped in ClientError.
The callback receives ClientError rather than the raw decoding error because the wrapped error includes operation and HTTP context. The raw decoding error remains available as ClientError.underlyingError.
The same ClientError would still be thrown to the caller.
Prior work
This builds on the discussion in:
Those PRs identified the same general production problem. This issue proposes a simpler model focused only on response decoding failures.
Problem
Generated client calls currently wrap response decoding failures in
ClientError, which gives useful context like operation ID, request, response, response body, cause, and the underlying decoding error.However, adopters do not have a central place to observe those decoding failures.
In production, this makes it hard to report response decoding problems consistently without wrapping every generated client call manually.
This works, but it is easy to miss call sites and it repeats the same reporting code across the app.
Middleware is useful for HTTP-level logging, but it observes the request/response around the transport call. The decoding failure happens later, when the runtime decodes the response body into the generated output type.
Proposed direction
Add a small callback on
Configurationfor response decoding failures:The callback would be called when response decoding fails, after the failure has been wrapped in
ClientError.The callback receives
ClientErrorrather than the raw decoding error because the wrapped error includes operation and HTTP context. The raw decoding error remains available asClientError.underlyingError.The same
ClientErrorwould still be thrown to the caller.Prior work
This builds on the discussion in:
Those PRs identified the same general production problem. This issue proposes a simpler model focused only on response decoding failures.