{"record":{"id":"922a38e0ea1c1dfc","repo":"OpenNHP/opennhp","slug":"data-must-be-a-pointer","errorCode":null,"errorMessage":"data must be a pointer","messagePattern":"data must be a pointer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nhp/core/ztdo/ztdo.go","lineNumber":628,"sourceCode":"\t\t}\n\t}\n\n\treturn nil\n}\n\n// toBuffer provides unified way to serialize a Go struct into bytes buffer\nfunc toBuffer(data any) *bytes.Buffer {\n\tbuf := bytes.NewBuffer(nil)\n\t_ = marshal(buf, data)\n\treturn buf\n}\n\n// toStructure provides unified way to deserialize bytes from a file into a Go struct\nfunc toStructure(f *os.File, data any) error {\n\tlengthMap = make(map[string]uint32)\n\trValues := reflect.ValueOf(data)\n\tif rValues.Kind() != reflect.Pointer {\n\t\treturn fmt.Errorf(\"data must be a pointer\")\n\t}\n\treturn unmarshal(f, data)\n}\n\n// setBytes provides unified way to set bytes to a slice or array\nfunc setBytes(rvalue reflect.Value, dst []byte) {\n\tif rvalue.Kind() == reflect.Slice {\n\t\trvalue.SetBytes(dst)\n\t} else if rvalue.Kind() == reflect.Array {\n\t\tlen := rvalue.Len()\n\t\telType := rvalue.Type().Elem()\n\n\t\tarrayType := reflect.ArrayOf(len, elType)\n\t\tnewArray := reflect.New(arrayType).Elem()\n\n\t\tfor i := range len {\n\t\t\tnewArray.Index(i).SetUint(uint64(dst[i]))\n\t\t}","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/nhp/core/ztdo/ztdo.go#L610-L646","documentation":"toStructure is the file-to-struct deserialization entry point and requires its data argument to be a pointer, because unmarshal writes into the destination via reflection and must be able to address it. Passing a non-pointer makes this impossible, so the function fails fast with this error before any reading occurs.","triggerScenarios":"Calling toStructure(f, someStruct) with a struct value instead of &someStruct; passing a non-pointer map/slice value; wrapper functions that accept `any` and forward a value instead of a pointer.","commonSituations":"Forgetting the & when passing a local struct; helper wrappers that accept `any` and forward without dereferencing; porting code from JSON APIs where non-pointer targets are sometimes allowed.","solutions":["Pass a pointer: toStructure(f, &myStruct).","If you have an `any`, assert it holds a non-nil pointer before calling.","Fix wrapper functions to require pointer parameters in their signatures.","Document the pointer requirement in the wrapper's API to catch this at the call site."],"exampleFix":"// before\nvar hdr Header\ntoStructure(f, hdr) // \"data must be a pointer\"\n// after\nvar hdr Header\nerr := toStructure(f, &hdr)","handlingStrategy":"type-guard","validationCode":"func ensurePtr(v any) bool { return reflect.ValueOf(v).Kind() == reflect.Pointer }","typeGuard":"if v := reflect.ValueOf(data); v.Kind() != reflect.Pointer || v.IsNil() {\n    return errors.New(\"toStructure requires a non-nil pointer\")\n}","tryCatchPattern":"if err := toStructure(f, data); err != nil {\n    if strings.Contains(err.Error(), \"data must be a pointer\") {\n        return fmt.Errorf(\"call toStructure(f, &value), not toStructure(f, value)\")\n    }\n    return err\n}","preventionTips":["Habitually pass &struct to deserialization APIs","Type wrapper functions as *T instead of any where possible","Lint for toStructure calls whose argument is not address-of"],"tags":["reflection","go","api-misuse","pointer"],"backgroundTag":"type-mismatch","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}