temporalio/temporal · error
failed to serialize handler result: %w
Error message
failed to serialize handler result: %w
What it means
writeResult serializes a Nexus handler's return value using the configured Serializer when it is not already a *nexus.Content. If serialization fails (the result type is not supported by the serializer), the handler writes a failure response with this error rather than the result.
Source
Thrown at common/nexus/nexusrpc/server.go:69
BaseHTTPHandler
options HandlerOptions
}
func (h *httpHandler) writeResult(writer http.ResponseWriter, request *http.Request, result any) {
var reader *nexus.Reader
if r, ok := result.(*nexus.Reader); ok {
// Close the request body in case we error before sending the HTTP request (which may double close but
// that's fine since we ignore the error).
// nolint:errcheck // ignore error on close
defer r.Close()
reader = r
} else {
content, ok := result.(*nexus.Content)
if !ok {
var err error
content, err = h.options.Serializer.Serialize(result)
if err != nil {
h.WriteFailure(writer, request, fmt.Errorf("failed to serialize handler result: %w", err))
return
}
}
header := maps.Clone(content.Header)
header["length"] = strconv.Itoa(len(content.Data))
reader = &nexus.Reader{
ReadCloser: io.NopCloser(bytes.NewReader(content.Data)),
Header: header,
}
}
header := writer.Header()
addContentHeaderToHTTPHeader(reader.Header, header)
if reader.ReadCloser == nil {
return
}
if _, err := io.Copy(writer, reader); err != nil {View on GitHub (pinned to bde624efd1)
Solutions
- Log the underlying serializer error to see which value/type failed to serialize.
- Convert the handler result to a type the serializer supports (e.g. build a *commonpb.Payload or a *nexus.Content).
- Register/choose a Serializer that supports all result types your handlers return.
- Ensure custom serializers implement Serialize for every type used in handler signatures.
Example fix
// before
func (h *Handler) Greet(ctx context.Context, input struct{}) (MyStruct, error) { return s, nil } // serializer cannot handle MyStruct
// after
payload, err := proto.Marshal(&s) // convert to supported Payload first
// or return *nexus.Content / *commonpb.Payload from the handler Defensive patterns
Strategy: validation
Validate before calling
// Ensure the handler's return value is serializable before registering
var _ = func(result any) error {
_, err := serializer.Serialize(result)
return err
} Type guard
func isSerializable(v any) bool {
if _, ok := v.(*nexus.Content); ok {
return true
}
if _, ok := v.(*commonpb.Payload); ok {
return true
}
return v == nil
} Try / catch
// Handler side: return serialization errors as handler failures
func (h *Handler) Op(ctx context.Context, in Input) (Output, error) {
out, err := doWork(in)
if err != nil {
return Output{}, nexus.HandlerErrorf(nexus.HandlerErrorTypeInternal, "work failed: %v", err)
}
return out, nil // ensure type matches serializer support
} Prevention
- Match handler result types to the registered Serializer's supported types
- Prefer returning proto payloads or nexus.Content from Nexus handlers
- Unit-test each handler end-to-end through the HTTP server once
- When adding a custom Serializer, cover every handler signature in tests
When it happens
Trigger: A Nexus operation handler returns a value that the registered payload serializer cannot serialize — e.g. an arbitrary struct when the serializer only accepts *commonpb.Payload or nil — and the result is written back to the HTTP response.
Common situations: Returning the wrong type from a handler (forgetting to convert a struct to a Payload); swapping in a custom Serializer that does not support the handler's result type; returning an unsupported concrete type from a typed handler whose serialization contract changed.
Related errors
- serializer error
- cannot serialize HSM task. unable to cast to expected type
- %w: cannot deserialize into %v
- %w: cannot serialize %v
- %w: payload marshal error: %w
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/ec66a5ead52018ff.
Report an issue: GitHub.