{"record":{"id":"68b19886acece36e","repo":"AlexxIT/go2rtc","slug":"tlv8-value-should-be-pointer","errorCode":null,"errorMessage":"tlv8: value should be pointer: ","messagePattern":"tlv8: value should be pointer: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/hap/tlv8/tlv8.go","lineNumber":203,"sourceCode":"\t\tdata, err = io.ReadAll(r)\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn Unmarshal(data, v)\n}\n\nfunc Unmarshal(data []byte, v any) error {\n\tif len(data) == 0 {\n\t\treturn errors.New(\"tlv8: unmarshal zero data\")\n\t}\n\n\tvalue := reflect.ValueOf(v)\n\tkind := value.Kind()\n\n\tif kind != reflect.Pointer {\n\t\treturn errors.New(\"tlv8: value should be pointer: \" + kind.String())\n\t}\n\n\tvalue = value.Elem()\n\tkind = value.Kind()\n\n\tif kind == reflect.Interface {\n\t\tvalue = value.Elem()\n\t\tkind = value.Kind()\n\t}\n\n\tswitch kind {\n\tcase reflect.Slice:\n\t\treturn unmarshalSlice(data, value)\n\tcase reflect.Struct:\n\t\treturn unmarshalStruct(data, value)\n\t}\n\n\treturn errors.New(\"tlv8: not implemented: \" + kind.String())","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/hap/tlv8/tlv8.go#L185-L221","documentation":"tlv8.Unmarshal requires its output parameter `v` to be a pointer so it can write decoded fields into the caller's value via reflection. When `v` is passed by value (e.g. a struct or map, not `&struct`), reflect.ValueOf(v).Kind() is not reflect.Pointer and this error is returned before any decoding happens. The kind that was actually received is appended to the message to help identify the mistake.","triggerScenarios":"Calling tlv8.Unmarshal(data, out), tlv8.UnmarshalBase64(in, out), or tlv8.UnmarshalReader(r, n, out) — and transitively the HAP client methods Dial, Pair, PairSetup, PairVerify — with a non-pointer `out` argument, such as Unmarshal(data, structValue) instead of Unmarshal(data, &structValue).","commonSituations":"Declaring the destination struct but forgetting the `&` when calling Unmarshal/UnmarshalBase64; passing an interface variable that wraps a non-pointer; copying a helper that accepted **T and calling it with T; intermediate variables like `var out MyStruct` passed directly in multi-return calls.","solutions":["Pass a pointer to the destination: tlv8.Unmarshal(data, &out) instead of tlv8.Unmarshal(data, out).","If the value is held in an interface variable, store a pointer in it: var out any = &MyStruct{} before calling Unmarshal.","If you only have a reflect.Value, verify rv.Kind() == reflect.Pointer && !rv.IsNil() before calling Unmarshal.","Check wrapper call sites (Dial, Pair, PairSetup, PairVerify, UnmarshalBase64, UnmarshalReader) and confirm the out argument you supply to them is addressable."],"exampleFix":"// before\nvar resp pairVerifyResponse\ntlv8.Unmarshal(data, resp)\n\n// after\nvar resp pairVerifyResponse\ntlv8.Unmarshal(data, &resp)","handlingStrategy":"type-guard","validationCode":"// before calling\ndata, err := base64.StdEncoding.DecodeString(in)\nif err != nil || len(data) == 0 {\n    return err\n}\n// ensure out is a non-nil pointer to struct/slice\nrv := reflect.ValueOf(out)\nif rv.Kind() != reflect.Pointer || rv.IsNil() {\n    return errors.New(\"out must be a non-nil pointer\")\n}","typeGuard":"func isDecodableTarget(v any) bool {\n    rv := reflect.ValueOf(v)\n    if rv.Kind() != reflect.Pointer || rv.IsNil() {\n        return false\n    }\n    k := rv.Elem().Kind()\n    return k == reflect.Struct || k == reflect.Slice\n}","tryCatchPattern":"// Go: handle the returned error, there is no panic\nif err := tlv8.UnmarshalBase64(in, &out); err != nil {\n    if strings.HasPrefix(err.Error(), \"tlv8: value should be pointer\") {\n        return fmt.Errorf(\"bad unmarshal target: %w\", err)\n    }\n    return err\n}","preventionTips":["Always declare the destination variable and pass &var to Unmarshal/UnmarshalBase64/UnmarshalReader.","Add a small wrapper in your codebase that type-asserts pointer targets before delegating to tlv8.","Watch for interface-typed parameters: store pointers inside interface values, not values.","Cover each unmarshal call site with a unit test so a dropped `&` fails immediately."],"tags":["tlv8","reflection","unmarshal","pointer-required","go"],"backgroundTag":"invalid-argument-value","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}