Skip to content

Conversation

@nerjs
Copy link

@nerjs nerjs commented Jan 19, 2026

Fixed #5226
Fixed #5089

Problem

When decoding server function responses, if the return type goes through the FromResponseParts path (for example SetHeader<SetCookie> and similar types), the following implementation is used:

impl<T: FromResponse<R>, E, R> RequestDecodeResult<T, R> for &&&ServerFnDecoder<Result<T, E>> {
type VerifyDecode = DecodeIsVerified;
fn decode_client_response(
&self,
res: Result<R, RequestError>,
) -> impl Future<Output = Result<Result<T, ServerFnError>, RequestError>> + Send {
SendWrapper::new(async move {
match res {
Err(err) => Err(err),
Ok(res) => Ok(T::from_response(res).await),
}
})
}
fn verify_can_deserialize(&self) -> Self::VerifyDecode {
DecodeIsVerified
}
}

In the current implementation, this path ignores the HTTP status code (for example 4xx/5xx) and the response body containing error details. As a result, a non-2xx response can be incorrectly decoded as a success (for example Ok(SetHeader { data: None })) when the expected header is missing. This masks real server errors and makes the behavior inconsistent compared to the DeserializeOwned decoding path.

Check for non-success status codes before attempting to decode response
parts. For error responses, parse the JSON error payload and convert it
to a ServerFnError::ServerError.

Also make ErrorPayload fields pub(crate) to allow internal access.
@nerjs nerjs requested a review from a team as a code owner January 19, 2026 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant