{"record":{"id":"cb3bde46c1616702","repo":"temporalio/temporal","slug":"serializer-error","errorCode":null,"errorMessage":"serializer error","messagePattern":"serializer error","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/nexus/payload_serializer.go","lineNumber":17,"sourceCode":"package nexus\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"maps\"\n\t\"mime\"\n\n\t\"github.com/nexus-rpc/sdk-go/nexus\"\n\tcommonpb \"go.temporal.io/api/common/v1\"\n\tenumspb \"go.temporal.io/api/enums/v1\"\n\t\"go.temporal.io/server/common/persistence/serialization\"\n)\n\ntype payloadSerializer struct{}\n\nvar errSerializer = errors.New(\"serializer error\")\n\n// Deserialize implements nexus.Serializer.\nfunc (payloadSerializer) Deserialize(content *nexus.Content, v any) error {\n\tpayloadRef, ok := v.(**commonpb.Payload)\n\tif !ok {\n\t\treturn fmt.Errorf(\"%w: cannot deserialize into %v\", errSerializer, v)\n\t}\n\n\tpayload := &commonpb.Payload{}\n\t*payloadRef = payload\n\tpayload.Metadata = make(map[string][]byte)\n\tpayload.Data = content.Data\n\n\th := maps.Clone(content.Header)\n\t// We assume that encoding is handled by the transport layer and the content is decoded.\n\tdelete(h, \"encoding\")\n\t// Length can safely be ignored.\n\tdelete(h, \"length\")","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/nexus/payload_serializer.go#L1-L35","documentation":"errSerializer is the base sentinel error for the nexus payloadSerializer in common/nexus/payload_serializer.go. Serialize and Deserialize wrap it (with fmt.Errorf \"%w: ...\") when the value being (de)serialized is not the expected *commonpb.Payload type or the underlying persistence serialization fails. Because it is wrapped, callers can match it with errors.Is.","triggerScenarios":"Calling Deserialize with a target that is not **commonpb.Payload; calling Serialize with an unsupported value; or an underlying serialization failure while converting between nexus Content and Payload.","commonSituations":"Passing arbitrary Go values (strings, structs) to the nexus serializer instead of Payload pointers; using a custom serializer with mismatched expectations; corrupted payloads from persistence failing to deserialize.","solutions":["Check errors.Is(err, nexus.ErrSerializer) and read the wrapped detail for the actual cause","Pass **commonpb.Payload (pointer-to-pointer) as the value for Deserialize","For custom types, implement nexus.Serializer instead of relying on the default payload serializer","Inspect the payload data for corruption if the wrapped cause is a persistence serialization failure"],"exampleFix":"// before\nvar s string\ncerr := serializer.Deserialize(content, &s)\n// after\nvar payload *commonpb.Payload\nif err := serializer.Deserialize(content, &payload); err != nil {\n    if errors.Is(err, nexus.ErrSerializer) { /* handle type/serialization mismatch */ }\n}","handlingStrategy":"type-guard","validationCode":"func asPayload(v any) (*commonpb.Payload, bool) {\n    p, ok := v.(*commonpb.Payload)\n    return p, ok && p != nil\n}","typeGuard":"payloadRef, ok := v.(**commonpb.Payload)\nif !ok { return fmt.Errorf(\"%w: cannot deserialize into %v\", nexus.ErrSerializer, v) }","tryCatchPattern":"if err := serializer.Deserialize(content, &payload); err != nil {\n    if errors.Is(err, nexus.ErrSerializer) {\n        // inspect wrapped cause: wrong target type vs corrupted data\n    }\n}","preventionTips":["Always pass **commonpb.Payload to Deserialize and *commonpb.Payload to Serialize","Use errors.Is against the sentinel rather than string matching","Validate payload data integrity (metadata, encoding) before deserializing user content"],"tags":["nexus","serialization","payload"],"backgroundTag":"serialization-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}