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

  1. Pick one parameter style for the invocation and apply it to all arguments.
  2. Inspect the shortcode template to see whether it calls .Get(int) (positional) or .Get(key) (named) and align the call.
  3. 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

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


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/9c5f246056cadb74. Report an issue: GitHub.