{"record":{"id":"506e9ca2b42eef5f","repo":"temporalio/temporal","slug":"failed-to-deserialize-component-w","errorCode":null,"errorMessage":"failed to deserialize component: %w","messagePattern":"failed to deserialize component: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"chasm/tree.go","lineNumber":619,"sourceCode":"\t\tmetadata := n.serializedNode.Metadata\n\t\tcomponentAttr := metadata.GetComponentAttributes()\n\t\tif componentAttr == nil {\n\t\t\treturn softassert.UnexpectedInternalErr(\n\t\t\t\tn.logger,\n\t\t\t\t\"expect chasm node to have ComponentAttributes\",\n\t\t\t\tfmt.Errorf(\"actual attributes: %v\", metadata.Attributes))\n\t\t}\n\n\t\tregistrableComponent, ok := n.registry.ComponentByID(componentAttr.GetTypeId())\n\t\tif !ok {\n\t\t\treturn softassert.UnexpectedInternalErr(\n\t\t\t\tn.logger,\n\t\t\t\t\"unknown component type ID\",\n\t\t\t\tfmt.Errorf(\"%d\", componentAttr.GetTypeId()))\n\t\t}\n\n\t\tif err := n.deserialize(registrableComponent.goType); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to deserialize component: %w\", err)\n\t\t}\n\t}\n\n\t// For now, we assume if a node is accessed with a MutableContext,\n\t// its value will be mutated and no longer in sync with the serializedNode.\n\t_, componentCanBeMutated := chasmContext.(MutableContext)\n\tif componentCanBeMutated {\n\t\tn.setValueState(valueStateNeedSyncStructure)\n\t}\n\n\treturn nil\n}\n\nfunc (n *Node) prepareDataValue(\n\tchasmContext Context,\n\tvalueT reflect.Type,\n) error {\n\tmetadata := n.serializedNode.Metadata","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/chasm/tree.go#L601-L637","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Verify the component type registration (type ID mapping) matches what was used when the node was written","Check whether the component's proto/Go payload schema changed and add backward-compatible decoding or a migration","Inspect the persisted serializedNode payload for the failing node to confirm corruption vs schema mismatch","Ensure nodes are initialized (serialize written) before being accessed with a chasm Context"],"exampleFix":"// before\nc type MyComponent struct { Payload string } // renamed field, old data has 'payload' json tag\n// after\n// keep old wire name or add compatible proto field so old payloads still decode\n type MyComponent struct { Payload string `json:\"payload\"` }","handlingStrategy":"validation","validationCode":"// Before deploying, ensure the registered component type ID and payload schema are unchanged,\n// or that old payloads still decode:\nvar c MyComponent\nif err := proto.Unmarshal(storedBytes, &c); err != nil {\n  // migration needed before accessing existing nodes\n}","typeGuard":"func isDeserializable[T any](data []byte) bool { var v T; return proto.Unmarshal(data, &v) == nil }","tryCatchPattern":"if err := ctx.ExecutePureTask(fn, args...); err != nil {\n  if strings.Contains(err.Error(), \"failed to deserialize component\") {\n    logger.Error(\"component payload incompatible with registered type\", tag.Error(err))\n  }\n  return err\n}","preventionTips":["Never change a component's proto/Go payload schema without backward compatibility or a migration","Keep component type ID registrations stable across deployments","Always initialize (serialize) nodes before accessing them with a Context","Add a deploy-time test that deserializes sample persisted payloads"],"tags":["go","chasm","deserialization","persistence"],"backgroundTag":"deserialization-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}