gohugoio/hugo · error
%s: invalid state: invalid param type %T for shortcode %q, e
Error message
%s: invalid state: invalid param type %T for shortcode %q, expected a slice
What it means
Mirror of the named-param case: while collecting positional (space-separated) parameters, the parser found the shortcode's params field already held a non-slice value (typically a map[string]any from earlier named key=value args). The current token is positional but the existing state is a map, so appending to a slice fails. As with the sibling error, this signals mixed named/positional parameter styles within a single shortcode invocation.
Source
Thrown at hugolib/shortcode.go:704
} else {
if params, ok := sc.params.(map[string]any); ok {
params[currItem.ValStr(source)] = pt.Next().ValTyped(source)
} else {
return sc, fmt.Errorf("%s: invalid state: invalid param type %T for shortcode %q, expected a map", errorPrefix, params, sc.name)
}
}
} else {
// positional params
if sc.params == nil {
var params []any
params = append(params, currItem.ValTyped(source))
sc.params = params
} else {
if params, ok := sc.params.([]any); ok {
params = append(params, currItem.ValTyped(source))
sc.params = params
} else {
return sc, fmt.Errorf("%s: invalid state: invalid param type %T for shortcode %q, expected a slice", errorPrefix, params, sc.name)
}
}
}
case currItem.IsDone():
if !currItem.IsError() {
if !closed && sc.needsInner() {
return sc, fmt.Errorf("%s: shortcode %q must be closed or self-closed", errorPrefix, sc.name)
}
}
// handled by caller
pt.Backup()
break Loop
}
}
return sc, nil
}
View on GitHub (pinned to 52c9bd7908)
Solutions
- Pick one parameter style for the invocation and apply it to all arguments.
- Inspect the shortcode template to see whether it calls .Get(int) (positional) or .Get(key) (named) and align the call.
- Use the error prefix location to jump to the exact content file and fix the mixed invocation.
Example fix
// before
{{< mysc key="x" positionalval >}}
// after (all named)
{{< mysc key="x" second="positionalval" >}} Defensive patterns
Strategy: validation
Validate before calling
func validateShortcodeParams(tokens []scToken) error {
seenNamed, seenPositional := false, false
for _, t := range tokens {
if t.isNamedParam() { seenNamed = true }
if t.isPositional() { seenPositional = true }
if seenNamed && seenPositional {
return fmt.Errorf("shortcode %q mixes named and positional params", tokens[0].name)
}
}
return nil
} Prevention
- Never interleave key=value and bare values in one shortcode call.
- Document each shortcode's param convention at the top of its template.
- Add a content lint step that flags '=' alongside bare params.
When it happens
Trigger: A shortcode call that starts with named arguments then adds positional ones, e.g. {{< mysc key="x" positionalval >}}. After sc.params is set to map[string]any, a later positional token hits the branch at shortcode.go:700-704 and fails.
Common situations: Editing an existing named-parameter shortcode invocation and appending a bare positional value; inconsistent partial template includes passing mixed args; content migrated between shortcodes with different param conventions.
Related errors
- %s: invalid state: invalid param type %T for shortcode %q, e
- no compatible template found for shortcode %q in %s
- %s: shortcode %q must be closed or self-closed
- failed to process shortcode: %w
- can't divide the value by 0
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/9c5f246056cadb74.
Report an issue: GitHub.