temporalio/temporal · error

failed to deserialize component: %w

Error message

failed to deserialize component: %w

What it means

In chasm/tree.go, when a component node's value is needed (valueStateNeedDeserialize), Node.deserialize(goType) decodes the persisted serializedNode payload into the registered Go type. If that deserialization fails, the error is wrapped with 'failed to deserialize component'. This indicates persisted component state cannot be decoded into the currently registered component type.

Source

Thrown at chasm/tree.go:619

		metadata := n.serializedNode.Metadata
		componentAttr := metadata.GetComponentAttributes()
		if componentAttr == nil {
			return softassert.UnexpectedInternalErr(
				n.logger,
				"expect chasm node to have ComponentAttributes",
				fmt.Errorf("actual attributes: %v", metadata.Attributes))
		}

		registrableComponent, ok := n.registry.ComponentByID(componentAttr.GetTypeId())
		if !ok {
			return softassert.UnexpectedInternalErr(
				n.logger,
				"unknown component type ID",
				fmt.Errorf("%d", componentAttr.GetTypeId()))
		}

		if err := n.deserialize(registrableComponent.goType); err != nil {
			return fmt.Errorf("failed to deserialize component: %w", err)
		}
	}

	// For now, we assume if a node is accessed with a MutableContext,
	// its value will be mutated and no longer in sync with the serializedNode.
	_, componentCanBeMutated := chasmContext.(MutableContext)
	if componentCanBeMutated {
		n.setValueState(valueStateNeedSyncStructure)
	}

	return nil
}

func (n *Node) prepareDataValue(
	chasmContext Context,
	valueT reflect.Type,
) error {
	metadata := n.serializedNode.Metadata

View on GitHub (pinned to bde624efd1)

Solutions

  1. Verify the component type registration (type ID mapping) matches what was used when the node was written
  2. Check whether the component's proto/Go payload schema changed and add backward-compatible decoding or a migration
  3. Inspect the persisted serializedNode payload for the failing node to confirm corruption vs schema mismatch
  4. Ensure nodes are initialized (serialize written) before being accessed with a chasm Context

Example fix

// before
c type MyComponent struct { Payload string } // renamed field, old data has 'payload' json tag
// after
// keep old wire name or add compatible proto field so old payloads still decode
 type MyComponent struct { Payload string `json:"payload"` }
Defensive patterns

Strategy: validation

Validate before calling

// Before deploying, ensure the registered component type ID and payload schema are unchanged,
// or that old payloads still decode:
var c MyComponent
if err := proto.Unmarshal(storedBytes, &c); err != nil {
  // migration needed before accessing existing nodes
}

Type guard

func isDeserializable[T any](data []byte) bool { var v T; return proto.Unmarshal(data, &v) == nil }

Try / catch

if err := ctx.ExecutePureTask(fn, args...); err != nil {
  if strings.Contains(err.Error(), "failed to deserialize component") {
    logger.Error("component payload incompatible with registered type", tag.Error(err))
  }
  return err
}

Prevention

When it happens

Trigger: Accessing a CHASM component through validateAccess/validateAccessHelper or ExecutePureTask when the node's stored payload is corrupt, empty, or incompatible with the component's registered goType (e.g. proto payload changed, type ID remapped, or node was never properly initialized).

Common situations: Component struct/proto schema changed between deployments without migration, node created with a different component type sharing the same type ID, or corrupted persistence rows.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/506e9ca2b42eef5f. Report an issue: GitHub.