temporalio/temporal · error · serializer error
%w: cannot deserialize into %v
Error message
%w: cannot deserialize into %v
What it means
The Temporal payloadSerializer implements nexus.Serializer and only accepts a **commonpb.Payload as the Deserialize output target, because it converts Nexus Content into Temporal payloads. Passing any other pointer type (e.g. **nexus.Content for a different serializer contract, or a struct pointer) is a type mismatch and returns this wrapped errSerializer.
Source
Thrown at common/nexus/payload_serializer.go:23
"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")
if len(h) > 1 {
setUnknownNexusContent(h, payload.Metadata)
return nil
}
View on GitHub (pinned to bde624efd1)
Solutions
- Pass a **commonpb.Payload as the output parameter when using the Temporal payload serializer.
- Check which Serializer is registered in nexus HandlerServerOptions and use the matching input/output types in handlers.
- If handlers should use plain Go types, use the default nexus.Serializer instead of the Temporal one.
- Inspect the wrapping error's %v suffix — it prints the actual value passed — to spot the type mismatch.
Example fix
// before var out string err := serializer.Deserialize(content, &out) // not **commonpb.Payload // after var payload *commonpb.Payload err := serializer.Deserialize(content, &payload)
Defensive patterns
Strategy: type-guard
Validate before calling
func canDeserializeWithTemporalSerializer(v any) bool {
_, ok := v.(**commonpb.Payload)
return ok
} Type guard
func deserializePayload(content *nexus.Content) (*commonpb.Payload, error) {
var p *commonpb.Payload
if err := payloadSerializer{}.Deserialize(content, &p); err != nil {
return nil, err
}
return p, nil
} Try / catch
var payload *commonpb.Payload
if err := serializer.Deserialize(content, &payload); err != nil {
return nil, fmt.Errorf("nexus input is not a temporal payload: %w", err)
} Prevention
- Only pass **commonpb.Payload targets to the Temporal payload serializer
- Check which Serializer is set in HandlerServerOptions before writing handler signatures
- Use the default nexus.Serializer for arbitrary Go types
- Add one round-trip Serialize/Deserialize test per serializer configuration
When it happens
Trigger: Calling payloadSerializer.Deserialize(content, v) where v is not **commonpb.Payload — e.g. passing *string, **struct, or a *nexus.Content target — typically from the anonymous handler plumbing that deserializes Nexus operation inputs.
Common situations: Mixing serializers: using the Temporal payload serializer with handlers written for the default nexus.Serializer (or vice versa); misconfigured Server options that install the wrong serializer; hand-written test code calling Deserialize with the wrong target type.
Related errors
- %w: cannot serialize %v
- serializer error
- cannot serialize HSM task. unable to cast to expected type
- failed to serialize handler result: %w
- %w: payload marshal error: %w
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/7df118f9537ccb62.
Report an issue: GitHub.