gocolly/colly · error
Invalid type or nil-pointer
Error message
Invalid type or nil-pointer
What it means
UnmarshalHTML requires its first argument to be a non-nil pointer to the struct being populated. If v is not a pointer or is a nil pointer, it returns "Invalid type or nil-pointer" (unmarshal.go:55) via reflection checks on reflect.ValueOf(v).
Source
Thrown at unmarshal.go:55
// Allowed struct tags:
// - "selector" (required): CSS (goquery) selector of the desired data
// - "attr" (optional): Selects the matching element's attribute's value.
// Leave it blank or omit to get the text of the element.
//
// Example struct declaration:
//
// type Nested struct {
// String string `selector:"div > p"`
// Classes []string `selector:"li" attr:"class"`
// Struct *Nested `selector:"div > div"`
// }
//
// Supported types: struct, *struct, string, []string
func UnmarshalHTML(v interface{}, s *goquery.Selection, structMap map[string]string) error {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return errors.New("Invalid type or nil-pointer")
}
sv := rv.Elem()
st := reflect.TypeOf(v).Elem()
if structMap != nil {
for k, v := range structMap {
attrV := sv.FieldByName(k)
if !attrV.CanAddr() || !attrV.CanSet() {
continue
}
if err := unmarshalSelector(s, attrV, v); err != nil {
return err
}
}
} else {
for i := 0; i < sv.NumField(); i++ {
attrV := sv.Field(i)
if !attrV.CanAddr() || !attrV.CanSet() {View on GitHub (pinned to 17d1d6ca92)
Solutions
- Pass a pointer to your struct: UnmarshalHTML(&result, sel, nil)
- Initialize the pointer before the call (result := &MyStruct{})
- Check the argument's type at the call site; only *struct is accepted
- Handle the returned error to catch programming mistakes early
Example fix
// before
var s MyStruct
colly.UnmarshalHTML(s, sel, nil)
// after
s := &MyStruct{}
err := colly.UnmarshalHTML(s, sel, nil) Defensive patterns
Strategy: validation
Validate before calling
if v == nil || reflect.ValueOf(v).Kind() != reflect.Ptr || reflect.ValueOf(v).IsNil() {
return fmt.Errorf("UnmarshalHTML needs a non-nil struct pointer")
} Type guard
func isUnmarshalTarget(v interface{}) bool {
rv := reflect.ValueOf(v)
return rv.Kind() == reflect.Ptr && !rv.IsNil() && rv.Elem().Kind() == reflect.Struct
} Try / catch
if err := colly.UnmarshalHTML(&result, sel, nil); err != nil {
if err.Error() == "Invalid type or nil-pointer" {
log.Println("check argument: must be non-nil *struct")
}
return err
} Prevention
- Always pass &T{} not T{} to unmarshal functions
- Initialize pointer targets before calling
- Add a unit test exercising each Unmarshal call site
- Keep struct targets non-generic so reflection kinds are predictable
When it happens
Trigger: Calling colly.UnmarshalHTML with a struct value instead of &struct, or with a nil pointer variable; also propagated when nested UnmarshalHTML calls receive non-pointer elements.
Common situations: Passing MyStruct{} instead of &MyStruct{}; a typed nil (*MyStruct)(nil); map/slice elements that are values not pointers; misusing the API after switching from Unmarshal to UnmarshalHTML.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
AI-assisted analysis of gocolly/colly@17d1d6ca92 (2026-08-30).
Data as JSON: /api/errors/680aa3763d6feaf9.
Report an issue: GitHub.