gocolly/colly · error
Invalid type:
Error message
Invalid type:
What it means
unmarshalSelector maps a struct field tagged with `selector` to part of the DOM. It supports struct, slice, and pointer field kinds; any other kind (string, int, etc.) reaches the default branch and returns "Invalid type: <value>" (unmarshal.go:115). The value's kind is not a supported selector target.
Source
Thrown at unmarshal.go:115
}
case reflect.String:
var val string
if selector == "" && htmlAttr != "" {
val = getDOMValue(s, htmlAttr)
} else {
val = getDOMValue(s.Find(selector), htmlAttr)
}
attrV.Set(reflect.Indirect(reflect.ValueOf(val)))
case reflect.Struct:
if err := unmarshalStruct(s, selector, attrV); err != nil {
return err
}
case reflect.Ptr:
if err := unmarshalPtr(s, selector, attrV); err != nil {
return err
}
default:
return errors.New("Invalid type: " + attrV.String())
}
return nil
}
func unmarshalAttr(s *goquery.Selection, attrV reflect.Value, attrT reflect.StructField) error {
selector := attrT.Tag.Get("selector")
//selector is "-" specify that field should ignore.
if selector == "-" {
return nil
}
htmlAttr := attrT.Tag.Get("attr")
// TODO support more types
switch attrV.Kind() {
case reflect.Slice:
if err := unmarshalSlice(s, selector, htmlAttr, attrV); err != nil {
return err
}
case reflect.String:View on GitHub (pinned to 17d1d6ca92)
Solutions
- Change the field type to a struct, *struct, or slice of structs
- Move the selector tag to the struct level (on the struct type passed to UnmarshalHTML) for scalar capture via `map` tags or use `attr`-style handling
- Remove the selector tag if the field is not meant for DOM binding
- Check field kinds against the supported list in unmarshal.go
Example fix
// before
type Item struct {
Title string `selector:"h1"`
}
// after
type Title struct {
Text string `selector:"h1"`
}
type Item struct {
Title Title `selector:""`
} Defensive patterns
Strategy: validation
Validate before calling
// before unmarshaling, verify selector-tagged fields are struct/slice/pointer kinds
for _, f := range reflect.VisibleFields(reflect.TypeOf(Item{})) {
if f.Tag.Get("selector") != "" {
k := f.Type.Kind()
if k != reflect.Struct && k != reflect.Slice && k != reflect.Ptr {
panic("field " + f.Name + " has selector tag but unsupported kind")
}
}
} Try / catch
if err := colly.UnmarshalHTML(&result, sel, nil); err != nil {
if strings.HasPrefix(err.Error(), "Invalid type:") {
log.Printf("schema error: %v", err)
}
return err
} Prevention
- Never put selector tags on scalar (string/int) fields
- Keep a compile-time test that unmarshals a sample document in CI
- Wrap scalars in structs when DOM binding is needed
- Document the supported field kinds in your schema package
When it happens
Trigger: Declaring a struct field with a `selector:"..."` tag whose type is not struct, []struct, or *struct — e.g. a plain string field with a selector tag — then calling UnmarshalHTML/Unmarshal.
Common situations: Assuming `selector` tags work on scalar fields like strings; copying tags from struct-level examples onto primitive fields; schema drift after refactoring field types.
Related errors
AI-assisted analysis of gocolly/colly@17d1d6ca92 (2026-08-30).
Data as JSON: /api/errors/3c6b2b915d43a0d5.
Report an issue: GitHub.