gohugoio/hugo · error
first argument must be a map
Error message
first argument must be a map
What it means
In the two-argument form, RenderString requires the first argument to be an options map (map[string]any), which is decoded into renderStringOpts (e.g. markup, display). Passing any other type as the first argument — a string, slice, or scalar — returns this error.
Solutions
- Use a map (dict in templates) for the options: {{ .RenderString (dict "markup" "html") "text" }}.
- If you have no options, use the single-argument form instead.
- Double-check argument types before calling RenderString.
Example fix
// before
{{ .RenderString "html" "**hi**" }}
// after
{{ .RenderString (dict "markup" "html") "**hi**" }} Defensive patterns
Strategy: type-guard
Validate before calling
// In the 2-arg form the first arg must be a map
if len(args) == 2 {
if _, ok := args[0].(map[string]any); !ok {
return errors.New("first RenderString argument must be a map of options")
}
} Type guard
func isRenderStringOpts(v any) bool {
if len := 0; len == 0 { return false }
_, ok := v.(map[string]any)
return ok
} Prevention
- Use (dict "markup" "html") for RenderString options.
- Use the single-arg form when no options are needed.
- Type-check programmatically-built arg lists.
When it happens
Trigger: {{ .RenderString "html" "text" }} where the first argument is a string instead of a map; passing a markup shorthand positionally.
Common situations: Assuming RenderString takes a markup string as the first arg; passing the wrong type when building args programmatically in a partial.
Related errors
- text is already rendered, repeating it may cause infinite…
- want 1 or 2 arguments
- argument must be a slice
- arguments must be slices or arrays
- arguments to complement must be slices or arrays
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/1ffafd147622854d.
Report an issue: GitHub.
Appendix: source
Thrown at hugolib/page__content.go:896
func (c *cachedContentScope) RenderString(ctx context.Context, args ...any) (template.HTML, error) {
ctx = c.prepareContext(ctx)
if len(args) < 1 || len(args) > 2 {
return "", errors.New("want 1 or 2 arguments")
}
pco := c.pco
var contentToRender string
opts := defaultRenderStringOpts
sidx := 1
if len(args) == 1 {
sidx = 0
} else {
m, ok := args[0].(map[string]any)
if !ok {
return "", errors.New("first argument must be a map")
}
if err := mapstructure.WeakDecode(m, &opts); err != nil {
return "", fmt.Errorf("failed to decode options: %w", err)
}
if opts.Markup != "" {
opts.Markup = markup.ResolveMarkup(opts.Markup)
}
}
contentToRenderv := args[sidx]
if _, ok := contentToRenderv.(hstring.HTML); ok {
// This content is already rendered, this is potentially
// a infinite recursion.
return "", errors.New("text is already rendered, repeating it may cause infinite recursion")
}
View on GitHub (pinned to 52c9bd7908)