gohugoio/hugo · error
slice of untyped nil
Error message
slice of untyped nil
What it means
Raised by the `slice` template action (`{{slice .X 1 2}}`) when the first argument is an untyped nil — i.e. `indirectInterface` returned an invalid reflect.Value (funcs.go:244-245). `slice` requires a string, slice, or array; nil satisfies none. Equivalent to calling Go's `s[1:2]` on a bare `var x interface{} = nil`.
Source
Thrown at tpl/internal/go_templates/texttemplate/funcs.go:245
// the loop holds invariant: item.IsValid()
panic("unreachable")
default:
return reflect.Value{}, fmt.Errorf("can't index item of type %s", item.Type())
}
}
return item, nil
}
// Slicing.
// slice returns the result of slicing its first argument by the remaining
// arguments. Thus "slice x 1 2" is, in Go syntax, x[1:2], while "slice x"
// is x[:], "slice x 1" is x[1:], and "slice x 1 2 3" is x[1:2:3]. The first
// argument must be a string, slice, or array.
func slice(item reflect.Value, indexes ...reflect.Value) (reflect.Value, error) {
item = indirectInterface(item)
if !item.IsValid() {
return reflect.Value{}, fmt.Errorf("slice of untyped nil")
}
var isNil bool
if item, isNil = indirect(item); isNil {
return reflect.Value{}, fmt.Errorf("slice of nil pointer")
}
if len(indexes) > 3 {
return reflect.Value{}, fmt.Errorf("too many slice indexes: %d", len(indexes))
}
var cap int
switch item.Kind() {
case reflect.String:
if len(indexes) == 3 {
return reflect.Value{}, fmt.Errorf("cannot 3-index slice a string")
}
cap = item.Len()
case reflect.Array, reflect.Slice:
cap = item.Cap()
default:View on GitHub (pinned to 52c9bd7908)
Solutions
- Wrap the slice in a nil guard: `{{with .MaybeSlice}}{{slice . 0 2}}{{end}}`.
- Provide a default via `{{slice (or .MaybeSlice "") 0 2}}` or a default slice in Go.
- Fix the data source so the field is always a populated string/slice.
- Use `{{if .MaybeSlice}}...{{end}}` to skip the action entirely when absent.
Example fix
// before
{{slice .Excerpt 0 100}} // .Excerpt is unset -> nil
// after
{{with .Excerpt}}{{slice . 0 100}}{{end}} Defensive patterns
Strategy: validation
Validate before calling
// In template, only slice when present and sliceable:
// {{with .MaybeSlice}}{{slice . 0 2}}{{end}}
// Or in Go, never pass nil — pass "" or an empty slice. Type guard
func isSliceableString(v interface{}) bool {
if v == nil { return false }
switch reflect.TypeOf(v).Kind() {
case reflect.String, reflect.Slice, reflect.Array:
return true
}
return false
} Prevention
- Always provide defaults for optional fields used in slice actions.
- Use {{with ...}} to skip the action when the value is absent.
- Avoid passing `interface{}` resolved nils into templates; coerce at the data boundary.
When it happens
Trigger: `{{slice .Missing 0 2}}` where `.Missing` is absent from the context and resolves to nil; `{{slice . 0 1}}` with a nil root; `{{slice (index .Map "absent") 0}}` because a missing map key yields the zero Value which becomes nil.
Common situations: Optional front matter field omitted on a page; shortcode param not provided and no default; map lookup that returns nothing; conditional content where the variable is only set in some branches.
Related errors
- slice of nil pointer
- too many slice indexes: %d
- cannot 3-index slice a string
- can't slice item of type %s
- invalid slice index: %d > %d
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/2bc6383fa3bfcb44.
Report an issue: GitHub.