temporalio/temporal · error
serializer error
Error message
serializer error
What it means
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.
Source
Thrown at common/nexus/payload_serializer.go:17
package nexus
import (
"errors"
"fmt"
"maps"
"mime"
"github.com/nexus-rpc/sdk-go/nexus"
commonpb "go.temporal.io/api/common/v1"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/server/common/persistence/serialization"
)
type payloadSerializer struct{}
var errSerializer = errors.New("serializer error")
// Deserialize implements nexus.Serializer.
func (payloadSerializer) Deserialize(content *nexus.Content, v any) error {
payloadRef, ok := v.(**commonpb.Payload)
if !ok {
return fmt.Errorf("%w: cannot deserialize into %v", errSerializer, v)
}
payload := &commonpb.Payload{}
*payloadRef = payload
payload.Metadata = make(map[string][]byte)
payload.Data = content.Data
h := maps.Clone(content.Header)
// We assume that encoding is handled by the transport layer and the content is decoded.
delete(h, "encoding")
// Length can safely be ignored.
delete(h, "length")View on GitHub (pinned to bde624efd1)
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
Example fix
// before
var s string
cerr := serializer.Deserialize(content, &s)
// after
var payload *commonpb.Payload
if err := serializer.Deserialize(content, &payload); err != nil {
if errors.Is(err, nexus.ErrSerializer) { /* handle type/serialization mismatch */ }
} Defensive patterns
Strategy: type-guard
Validate before calling
func asPayload(v any) (*commonpb.Payload, bool) {
p, ok := v.(*commonpb.Payload)
return p, ok && p != nil
} Type guard
payloadRef, ok := v.(**commonpb.Payload)
if !ok { return fmt.Errorf("%w: cannot deserialize into %v", nexus.ErrSerializer, v) } Try / catch
if err := serializer.Deserialize(content, &payload); err != nil {
if errors.Is(err, nexus.ErrSerializer) {
// inspect wrapped cause: wrong target type vs corrupted data
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cannot serialize HSM task. unable to cast to expected type
- failed to serialize handler result: %w
- %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/cb3bde46c1616702.
Report an issue: GitHub.