gohugoio/hugo · error

invalid path %q

Error message

invalid path %q

What it means

Returned by toPathSitesMap in hugolib/pagesfromdata/pagesfromgotmpl.go:74 when the map passed to a content adapter's AddPage (from a _content.gotmpl template) has a 'path' value that cannot be cast to a string. Every page created from a content adapter must have a string path, so Hugo rejects the entry immediately. Note the message interpolates the (empty) cast result, so it typically reads invalid path "".

Source

Thrown at hugolib/pagesfromdata/pagesfromgotmpl.go:74

	// The return value will always be an empty string.
	EnableAllLanguages() string
}

var _ PagesFromDataTemplateContext = (*pagesFromDataTemplateContext)(nil)

type pagesFromDataTemplateContext struct {
	p *PagesFromTemplate
}

func (p *pagesFromDataTemplateContext) toPathSitesMap(v any) (string, map[string]any, map[string]any, error) {
	m, err := hmaps.ToStringMapE(v)
	if err != nil {
		return "", nil, nil, err
	}

	path, err := cast.ToStringE(m["path"])
	if err != nil {
		return "", nil, nil, fmt.Errorf("invalid path %q", path)
	}

	sites := hmaps.ToStringMap(m["sites"])

	return path, sites, m, nil
}

func (p *pagesFromDataTemplateContext) AddPage(v any) (string, error) {
	path, sites, m, err := p.toPathSitesMap(v)
	if err != nil {
		return "", err
	}

	hash, hasChanged := p.p.buildState.checkHasChangedAndSetSourceInfo(path, sites, m)
	if !hasChanged {
		return "", nil
	}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Ensure the dict passed to .AddPage has a 'path' key whose value is a plain string (e.g. "path" (printf "posts/%s" .id)).
  2. Print the offending item with warnf/debug in the template to see the actual type of .path.
  3. Coerce values explicitly in the template with the string func before adding the page.
  4. Validate the remote data shape (transform.Unmarshal result) before iterating.

Example fix

{{/* before: path is a map */}}
{{ $.AddPage (dict "path" .slugObject "title" .title) }}

{{/* after: path is a string */}}
{{ $.AddPage (dict "path" (string .slugObject.slug) "title" .title) }}
Defensive patterns

Strategy: validation

Validate before calling

// Validate paths passed to AddPage in content adapters (_content.gotmpl)
{{ $path := "posts/my-post" }}
{{ if or (strings.HasPrefix $path "/") (eq $path "") (in $path "..") }}
  {{ errorf "bad page path %q" $path }}
{{ end }}
{{ $.AddPage (dict "path" $path "title" "My Post") }}

Prevention

When it happens

Trigger: Calling $.AddPage in _content.gotmpl with a dict whose 'path' key is a non-string-castable value (a slice, map, or nil object from remote JSON), or where cast.ToStringE fails on the value type.

Common situations: Content adapters built over remote APIs where the expected field is missing or nested (passing the whole object instead of .path); building the path with a template pipeline that yields a slice; typo'd key so 'path' is absent and a non-castable zero value flows in; migrating data whose id field is numeric-array or object typed.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/846e5852bbbd0f81.json. Report an issue: GitHub ↗.