{"record":{"id":"d216e6b8730e0d64","repo":"jmoiron/sqlx","slug":"jsontext-unmarshaljson-on-nil-pointer","errorCode":null,"errorMessage":"JSONText: UnmarshalJSON on nil pointer","messagePattern":"JSONText: UnmarshalJSON on nil pointer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"types/types.go","lineNumber":73,"sourceCode":"// Value() validates the json format in the source, and returns an error if\n// the json is not valid.  Scan does no validation.  JSONText additionally\n// implements `Unmarshal`, which unmarshals the json within to an interface{}\ntype JSONText json.RawMessage\n\nvar emptyJSON = JSONText(\"{}\")\n\n// MarshalJSON returns the *j as the JSON encoding of j.\nfunc (j JSONText) MarshalJSON() ([]byte, error) {\n\tif len(j) == 0 {\n\t\treturn emptyJSON, nil\n\t}\n\treturn j, nil\n}\n\n// UnmarshalJSON sets *j to a copy of data\nfunc (j *JSONText) UnmarshalJSON(data []byte) error {\n\tif j == nil {\n\t\treturn errors.New(\"JSONText: UnmarshalJSON on nil pointer\")\n\t}\n\t*j = append((*j)[0:0], data...)\n\treturn nil\n}\n\n// Value returns j as a value.  This does a validating unmarshal into another\n// RawMessage.  If j is invalid json, it returns an error.\nfunc (j JSONText) Value() (driver.Value, error) {\n\tvar m json.RawMessage\n\tvar err = j.Unmarshal(&m)\n\tif err != nil {\n\t\treturn []byte{}, err\n\t}\n\treturn []byte(j), nil\n}\n\n// Scan stores the src in *j.  No validation is done.\nfunc (j *JSONText) Scan(src interface{}) error {","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/jmoiron/sqlx/blob/41dac167fdad5e3fd81d66cafba0951dc6823a30/types/types.go#L55-L91","documentation":"JSONText.UnmarshalJSON implements json.Unmarshaler and requires a non-nil receiver, since it appends data into the existing slice. Calling it on a nil *JSONText would be unsafe/meaningless, so it returns this error. This typically surfaces when json.Unmarshal calls back into a nil pointer field.","triggerScenarios":"json.Unmarshal(data, (*types.JSONText)(nil)); unmarshaling into a nil JSONText pointer field in a struct; JSON libraries calling UnmarshalJSON through a nil receiver.","commonSituations":"Struct field declared as *JSONText left nil by another decoder step; manual re-use of a pointer variable that was reset to nil; passing a nil pointer obtained from a failed previous decode.","solutions":["Initialize the JSONText before unmarshaling: use a value (JSONText) field or allocate with new(types.JSONText).","Ensure the containing struct field is populated/allocated before json.Unmarshal runs.","If scanning from SQL, prefer GzippedText/JSONText value semantics (var t types.JSONText).","Wrap unmarshal and handle the error by allocating and retrying once."],"exampleFix":"// before\nvar t *types.JSONText\njson.Unmarshal(data, t) // nil pointer\n// after\nt := &types.JSONText{}\njson.Unmarshal(data, t)","handlingStrategy":"type-guard","validationCode":"func safeUnmarshalJSONText(data []byte, j **types.JSONText) error {\n\tif j == nil || *j == nil {\n\t\t*j = new(types.JSONText)\n\t}\n\treturn json.Unmarshal(data, j)\n}","typeGuard":"func nonNilJSONText(j *types.JSONText) *types.JSONText {\n\tif j == nil {\n\t\treturn new(types.JSONText)\n\t}\n\treturn j\n}","tryCatchPattern":"if err := json.Unmarshal(data, &t); err != nil {\n\tif strings.Contains(err.Error(), \"UnmarshalJSON on nil pointer\") {\n\t\tt = &types.JSONText{}\n\t\terr = json.Unmarshal(data, &t)\n\t}\n\treturn err\n}","preventionTips":["Declare JSONText fields by value, not *JSONText.","Always allocate pointer fields with new()/&{} before unmarshal.","Never pass a nil *JSONText directly to json.Unmarshal.","Handle decoder errors by re-initializing and retrying once."],"tags":["json","unmarshal","nil-pointer"],"backgroundTag":"unmarshal-nil-pointer","analyzedSha":"41dac167fdad5e3fd81d66cafba0951dc6823a30","analyzedAt":"2026-09-03T06:10:20.382Z","contentChangedAt":"2026-09-03T06:10:20.382Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}