gohugoio/hugo · critical

missing 'src' in metadata for resource

Error message

missing 'src' in metadata for resource

What it means

Returned by `assignMetadata` (resource_metadata.go:148-160) when iterating the resource `headless`/page-bundle metadata list and an entry has no `src` key. Every metadata rule must declare which resource(s) it targets via `src` (a glob, matched case-insensitively via `filepath.Match`). Missing `src` is treated as a config error because the rule would match nothing deterministically.

Solutions

  1. Add `src` to every metadata entry with a glob or filename matching the bundle's files.
  2. In YAML, ensure `src` is a key under the list item (same indentation as `name`/`title`).
  3. Use lowercase `src` (the key lookup is case-sensitive).
  4. Validate each entry has `src`, `name`, and/or `title` before building.

Example fix

# frontmatter -- before
resources:
  - name: hero
    title: Hero image

# after
resources:
  - src: images/hero*.jpg
    name: hero
    title: Hero image
Defensive patterns

Strategy: validation

Validate before calling

// Validate page-bundle frontmatter metadata before build.
func validateResourceMeta(meta []map[string]any) error {
	for i, m := range meta {
		if _, ok := m["src"]; !ok {
			return fmt.Errorf("metadata entry %d missing 'src'", i)
		}
	}
	return nil
}

Prevention

When it happens

Trigger: A page bundle frontmatter / `_index.md` headless-resource metadata block where a `[[resources]]` (TOML) or `resources:` list item (YAML) omits `src`, e.g. only declares `name` or `title`. Reached via `assignMetadata` during resource metadata binding.

Common situations: YAML indentation making `src` a sibling rather than a list-item field; copy-paste of a metadata block dropping the `src` line; typo like `Src` (case-sensitive key lookup); TOML `[[resources]]` table missing `src`; refactor that renamed `src` to `path`/`match`.

Related errors


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

Appendix: source

Thrown at resources/resource_metadata.go:159

}

// AssignMetadata assigns the given metadata to those resources that supports updates
// and matching by wildcard given in `src` using `filepath.Match` with lower cased values.
// This assignment is additive, but the most specific match needs to be first.
// The `name` and `title` metadata field support shell-matched collection it got a match in.
// See https://golang.org/pkg/path/#Match
func assignMetadata(metadata []map[string]any, ma *metaResource, counters map[string]int) error {
	var (
		nameSet, titleSet                   bool
		nameCounter, titleCounter           = 0, 0
		nameCounterFound, titleCounterFound bool
		resourceSrcKey                      = strings.ToLower(ma.Name())
	)

	for _, meta := range metadata {
		src, found := meta["src"]
		if !found {
			return fmt.Errorf("missing 'src' in metadata for resource")
		}

		srcKey := strings.ToLower(cast.ToString(src))

		glob, err := hglob.GetGlob(srcKey)
		if err != nil {
			return fmt.Errorf("failed to match resource with metadata: %w", err)
		}

		match := glob.Match(resourceSrcKey)

		if match {
			if !nameSet {
				name, found := meta["name"]
				if found {
					name := cast.ToString(name)
					// Bundled resources in sub folders are relative paths with forward slashes. Make sure any renames also matches that format:
					name = paths.TrimLeading(filepath.ToSlash(name))

View on GitHub (pinned to 52c9bd7908)