{"record":{"id":"eca2de79d4e3e6b2","repo":"ory/kratos","slug":"node-type-and-node-attributes-mismatch-t-s","errorCode":null,"errorMessage":"node type and node attributes mismatch: %T != %s","messagePattern":"node type and node attributes mismatch: %T != (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ui/node/node.go","lineNumber":569,"sourceCode":"\t\t\tattr.NodeType = Anchor\n\t\tcase *ImageAttributes:\n\t\t\tt = Image\n\t\t\tattr.NodeType = Image\n\t\tcase *ScriptAttributes:\n\t\t\tt = Script\n\t\t\tattr.NodeType = Script\n\t\tcase *DivisionAttributes:\n\t\t\tt = Division\n\t\t\tattr.NodeType = Division\n\t\tdefault:\n\t\t\treturn nil, errors.WithStack(fmt.Errorf(\"unknown node type: %T\", n.Attributes))\n\t\t}\n\t}\n\n\tif n.Type == \"\" {\n\t\tn.Type = t\n\t} else if n.Type != t {\n\t\treturn nil, errors.WithStack(fmt.Errorf(\"node type and node attributes mismatch: %T != %s\", n.Attributes, n.Type))\n\t}\n\n\tif n.Meta == nil {\n\t\tn.Meta = new(Meta)\n\t}\n\n\treturn json.Marshal((*jsonRawNode)(n))\n}\n","sourceCodeStart":551,"sourceCodeEnd":578,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/ui/node/node.go#L551-L578","documentation":"In MarshalJSON, the type derived from the concrete Attributes struct is compared against the value already set on n.Type. If they differ, the node is internally inconsistent — its declared type does not match its attributes — so serialization aborts to avoid emitting a corrupt payload.","triggerScenarios":"Setting n.Type = \"input\" while assigning n.Attributes = &TextAttributes{...} (or any mismatched pair), then marshaling the node; deserializing into a Node and manually changing Type before re-serializing.","commonSituations":"Hand-assembling flow UI nodes in tests or custom renderers; mapping external data into Node structs where Type is copied from one node and Attributes from another; mutating a parsed node's Type without updating Attributes.","solutions":["Set n.Type to the string constant matching the attributes struct (e.g. Input with *InputAttributes), or clear n.Type and let MarshalJSON derive it.","Compare the %T from the message against the %s type string to find the mismatched pair.","Use the library constructors/helpers for nodes instead of setting Type and Attributes independently.","When copying nodes, copy Type and Attributes together as a unit."],"exampleFix":"// before\nn := ui.Node{Type: ui.TypeInput, Attributes: &ui.TextAttributes{}}\n// after\nn := ui.Node{Type: ui.TypeText, Attributes: &ui.TextAttributes{NodeType: ui.Text}}","handlingStrategy":"validation","validationCode":"var expected ui.NodeType\nswitch a := n.Attributes.(type) {\ncase *ui.InputAttributes:\n    expected = ui.Input\ncase *ui.TextAttributes:\n    expected = ui.Text\n// ... other cases\ndefault:\n    return\n}\nif n.Type != \"\" && n.Type != expected {\n    // fix or clear n.Type before marshaling\n}","typeGuard":null,"tryCatchPattern":"if _, err := json.Marshal(node); err != nil && strings.Contains(err.Error(), \"node type and node attributes mismatch\") {\n    log.Error(\"inconsistent node\", \"err\", err) // Type field disagrees with Attributes\n}","preventionTips":["Construct nodes via helpers or set Attributes first and let MarshalJSON derive Type (leave Type empty).","When mutating parsed nodes, change Type and Attributes together.","Add round-trip tests for hand-assembled nodes."],"tags":["json","marshal","ui-nodes","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}