{"record":{"id":"98884ea69840a948","repo":"BoundaryML/baml","slug":"decodeunionvalue-valueunion-is-nil","errorCode":null,"errorMessage":"decodeUnionValue: valueUnion is nil","messagePattern":"decodeUnionValue: valueUnion is nil","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"engine/language_client_go/baml_go/serde/decode.go","lineNumber":226,"sourceCode":"func decodeEnumValue(valueEnum *cffi.CFFIValueEnum, typeMap TypeMap) (reflect.Value, reflect.Type) {\n\tif valueEnum == nil {\n\t\tpanic(\"decodeEnumValue: valueEnum is nil\")\n\t}\n\n\tgoType, ok := typeMap.GetType(valueEnum.Name)\n\tif !ok {\n\t\tdynamicEnum := DynamicEnum{Name: valueEnum.Name.Name, Value: valueEnum.Value}\n\t\treturn reflect.ValueOf(dynamicEnum), reflect.TypeOf(DynamicEnum{})\n\t}\n\tenum := reflect.New(goType)\n\tas_interface := enum.Interface().(BamlEnumDeserializer)\n\tas_interface.Decode(valueEnum, typeMap)\n\treturn enum.Elem(), goType\n}\n\nfunc decodeUnionValue(valueUnion *cffi.CFFIValueUnionVariant, typeMap TypeMap) (reflect.Value, reflect.Type) {\n\tif valueUnion == nil {\n\t\tpanic(\"decodeUnionValue: valueUnion is nil\")\n\t}\n\n\tvalue, goType := func() (reflect.Value, reflect.Type) {\n\t\tif ok := valueUnion.Value.GetNullValue(); ok != nil {\n\t\t\t// If the union value is null, return nil\n\t\t\treturn reflect.ValueOf(nil), nil\n\t\t} else if valueUnion.IsSinglePattern {\n\t\t\t// For optional patterns (T | null), decode the inner value directly\n\t\t\t// These shouldn't be looked up as union types\n\t\t\t// Ignore the union-ness of it and just decode the inner value\n\t\t\treturn Decode(valueUnion.Value, typeMap)\n\t\t} else {\n\t\t\tgoType, ok := typeMap.GetType(valueUnion.Name)\n\t\t\tif !ok {\n\t\t\t\t// Union not found\n\t\t\t\t// This is a fully dynamic union, so we\n\t\t\t\t// decode the value as the value and drop\n\t\t\t\t// union type information","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_go/baml_go/serde/decode.go#L208-L244","documentation":"decodeUnionValue panics when handed a nil *cffi.CFFIValueUnionVariant. The decoder requires a non-nil union variant to determine the value's type; a nil pointer is an internal invariant violation in the FFI value decoding path reached through Decode.","triggerScenarios":"Decode() on a value whose CFFI representation has a nil value union — e.g. a malformed or nil CFFIValue inside a decoded response.","commonSituations":"Runtime/generator version mismatch producing values the Go serde cannot interpret, corrupted native responses, or a bug in BAML's value encoding.","solutions":["Check for a nil value before calling Decode and treat it as an empty/null result","Regenerate baml_client and align the BAML runtime version with the Go bindings","Catch the panic at the boundary with recover() if you must survive malformed data","File a bug with BAML including the BAML schema and payload that triggered it"],"exampleFix":"// before\nval, typ := serde.Decode(value, typeMap)\n// after\nif value == nil || value.Value == nil {\n  return reflect.Value{}, nil\n}\nval, typ := serde.Decode(value, typeMap)","handlingStrategy":"type-guard","validationCode":"if value == nil || value.Value == nil { return reflect.Value{}, nil }","typeGuard":"func decodable(v *cffi.CFFIValue) bool { return v != nil && v.Value != nil }","tryCatchPattern":"func safeDecode(v *cffi.CFFIValue, tm serde.TypeMap) (out reflect.Value) {\n  defer func() { if r := recover(); r != nil { out = reflect.Value{} } }()\n  v2, _ := serde.Decode(v, tm)\n  return v2\n}","preventionTips":["Nil-check CFFI values before Decode","Regenerate the client when upgrading the BAML runtime","Add recover() around serde calls processing untrusted payloads"],"tags":["go","panic","decoding","null"],"backgroundTag":"null-argument","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}