{"record":{"id":"ec66a5ead52018ff","repo":"temporalio/temporal","slug":"failed-to-serialize-handler-result-w","errorCode":null,"errorMessage":"failed to serialize handler result: %w","messagePattern":"failed to serialize handler result: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/nexus/nexusrpc/server.go","lineNumber":69,"sourceCode":"\tBaseHTTPHandler\n\toptions HandlerOptions\n}\n\nfunc (h *httpHandler) writeResult(writer http.ResponseWriter, request *http.Request, result any) {\n\tvar reader *nexus.Reader\n\tif r, ok := result.(*nexus.Reader); ok {\n\t\t// Close the request body in case we error before sending the HTTP request (which may double close but\n\t\t// that's fine since we ignore the error).\n\t\t// nolint:errcheck // ignore error on close\n\t\tdefer r.Close()\n\t\treader = r\n\t} else {\n\t\tcontent, ok := result.(*nexus.Content)\n\t\tif !ok {\n\t\t\tvar err error\n\t\t\tcontent, err = h.options.Serializer.Serialize(result)\n\t\t\tif err != nil {\n\t\t\t\th.WriteFailure(writer, request, fmt.Errorf(\"failed to serialize handler result: %w\", err))\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\theader := maps.Clone(content.Header)\n\t\theader[\"length\"] = strconv.Itoa(len(content.Data))\n\n\t\treader = &nexus.Reader{\n\t\t\tReadCloser: io.NopCloser(bytes.NewReader(content.Data)),\n\t\t\tHeader:     header,\n\t\t}\n\t}\n\n\theader := writer.Header()\n\taddContentHeaderToHTTPHeader(reader.Header, header)\n\tif reader.ReadCloser == nil {\n\t\treturn\n\t}\n\tif _, err := io.Copy(writer, reader); err != nil {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/nexus/nexusrpc/server.go#L51-L87","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nfunc (h *Handler) Greet(ctx context.Context, input struct{}) (MyStruct, error) { return s, nil } // serializer cannot handle MyStruct\n// after\npayload, err := proto.Marshal(&s) // convert to supported Payload first\n// or return *nexus.Content / *commonpb.Payload from the handler","handlingStrategy":"validation","validationCode":"// Ensure the handler's return value is serializable before registering\nvar _ = func(result any) error {\n    _, err := serializer.Serialize(result)\n    return err\n}","typeGuard":"func isSerializable(v any) bool {\n    if _, ok := v.(*nexus.Content); ok {\n        return true\n    }\n    if _, ok := v.(*commonpb.Payload); ok {\n        return true\n    }\n    return v == nil\n}","tryCatchPattern":"// Handler side: return serialization errors as handler failures\nfunc (h *Handler) Op(ctx context.Context, in Input) (Output, error) {\n    out, err := doWork(in)\n    if err != nil {\n        return Output{}, nexus.HandlerErrorf(nexus.HandlerErrorTypeInternal, \"work failed: %v\", err)\n    }\n    return out, nil // ensure type matches serializer support\n}","preventionTips":["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"],"tags":["nexus","serialization","http-handler"],"backgroundTag":"serialization-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}