temporalio/temporal · error
unexpected response status: %q
Error message
unexpected response status: %q
What it means
httpStatusCodeToHandlerErrorType maps HTTP response statuses from a Nexus handler endpoint onto nexus.HandlerErrorType values. When the server returns a status code that has no mapping (not 4xx/5xx cases like 501, 503, or the upstream-timeout status), it returns this error because the SDK cannot classify the failure. It signals an unanticipated response from the peer, not a domain error.
Source
Thrown at common/nexus/nexusrpc/client.go:450
return nexus.HandlerErrorTypeConflict, nil
case http.StatusUnauthorized:
return nexus.HandlerErrorTypeUnauthenticated, nil
case http.StatusForbidden:
return nexus.HandlerErrorTypeUnauthorized, nil
case http.StatusNotFound:
return nexus.HandlerErrorTypeNotFound, nil
case http.StatusTooManyRequests:
return nexus.HandlerErrorTypeResourceExhausted, nil
case http.StatusInternalServerError:
return nexus.HandlerErrorTypeInternal, nil
case http.StatusNotImplemented:
return nexus.HandlerErrorTypeNotImplemented, nil
case http.StatusServiceUnavailable:
return nexus.HandlerErrorTypeUnavailable, nil
case nexus.StatusUpstreamTimeout:
return nexus.HandlerErrorTypeUpstreamTimeout, nil
default:
return "", fmt.Errorf("unexpected response status: %q", response.Status)
}
}
func retryBehaviorFromHeader(header http.Header) nexus.HandlerErrorRetryBehavior {
switch strings.ToLower(header.Get(headerRetryable)) {
case "true":
return nexus.HandlerErrorRetryBehaviorRetryable
case "false":
return nexus.HandlerErrorRetryBehaviorNonRetryable
default:
return nexus.HandlerErrorRetryBehaviorUnspecified
}
}
func getUnsuccessfulStateFromHeader(response *http.Response, body []byte) (nexus.OperationState, error) {
state := nexus.OperationState(response.Header.Get(headerOperationState))
switch state {
case nexus.OperationStateCanceled, nexus.OperationStateFailed:View on GitHub (pinned to bde624efd1)
Solutions
- Inspect the wrapped status in the error message and check server/proxy logs to find why that status was returned.
- Verify the Nexus endpoint URL, routing, and authentication so requests reach the actual handler instead of a proxy error page.
- Fix the server to return proper nexus.HandlerError failures (e.g. Unavailable, NotSupported) instead of raw HTTP errors like 500.
- If the status is a valid new Nexus status, upgrade the client SDK to a version that maps it.
Example fix
// before
if resp.StatusCode == http.StatusInternalServerError { /* client has no mapping -> error */ }
// after
// server side: return a proper handler failure instead of a bare 500
return nil, nexus.HandlerErrorf(nexus.HandlerErrorTypeInternal, "operation failed: %v", cause) Defensive patterns
Strategy: try-catch
Validate before calling
// Peek at endpoint health before calling operations
resp, err := http.Get(endpointURL)
if err == nil && (resp.StatusCode < 200 || resp.StatusCode > 299) && resp.StatusCode != http.StatusServiceUnavailable {
log.Printf("endpoint returned unmapped status %d; check proxy/auth", resp.StatusCode)
} Try / catch
result, err := client.ExecuteOperation(ctx, svc, op, input)
var statusErr *errors.StatusError // or inspect wrapped error string
if err != nil {
if strings.Contains(err.Error(), "unexpected response status") {
// unclassified peer/proxy failure: log raw status, decide retry vs abort
return fmt.Errorf("nexus endpoint misbehaving: %w", err)
}
return err
} Prevention
- Ensure the Nexus endpoint URL points directly at the handler service, not an auth-gated proxy
- Keep client and server nexusrpc SDK versions in sync
- Monitor for gateway-generated statuses (401/404/502) in endpoint metrics
- Make servers return nexus.HandlerError failures rather than raw HTTP errors
When it happens
Trigger: Calling a Nexus operation via the nexusrpc client when the HTTP handler (or an intermediary proxy/gateway) returns an unmapped status code, e.g. 400, 401, 404, 500, 502, or a nonstandard status, inside defaultErrorFromResponse.
Common situations: A reverse proxy or API gateway intercepting the request and returning 401/404/502; a misconfigured Nexus endpoint URL; a server-side bug returning 500 instead of a Nexus failure; a newer server returning statuses the older client SDK does not know.
Related errors
- bucket not found
- link type is empty
- link type contains invalid char (valid chars: alphanumeric,
- empty operation name
- empty operation token
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/ef868885c6805a85.
Report an issue: GitHub.