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

  1. Use a map (dict in templates) for the options: {{ .RenderString (dict "markup" "html") "text" }}.
  2. If you have no options, use the single-argument form instead.
  3. 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

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


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)