gohugoio/hugo · error

%T cannot be merged by language

Error message

%T cannot be merged by language

What it means

Returned by `Resources.MergeByLanguageInterface` (resources.go:261-267) when the argument cannot be asserted to `Resources`. This method is the generic `any`-typed entry point exposed so the template runtime can call `merge` on a resource list; it type-narrows at resources.go:262-264 and rejects anything that is not a `resource.Resources` slice.

Source

Thrown at resources/resource/resources.go:264

	}

	for _, rr := range r2 {
		if translated, ok := rr.(translatedResource); ok {
			if _, found := m[translated.TranslationKey()]; !found {
				result = append(result, rr)
			}
		}
	}
	return result
}

// MergeByLanguageInterface is the generic version of MergeByLanguage. It
// is here just so it can be called from the tpl package.
// This is for internal use.
func (r Resources) MergeByLanguageInterface(in any) (any, error) {
	r2, ok := in.(Resources)
	if !ok {
		return nil, fmt.Errorf("%T cannot be merged by language", in)
	}
	return r.MergeByLanguage(r2), nil
}

// Source is an internal template and not meant for use in the templates. It
// may change without notice.
type Source interface {
	Publish() error
}

type ResourceGetter interface {
	// Get locates the Resource with the given name in the current context (e.g. in .Page.Resources).
	//
	// It returns nil if no Resource could found, panics if name is invalid.
	Get(name any) Resource
}

type IsProbablySameResourceGetter interface {

View on GitHub (pinned to 52c9bd7908)

Solutions

  1. Pass a typed `resource.Resources` value -- typically `.Resources` from a page bundle or `resources.Match`/`resources.Get` results.
  2. If you have a `[]any`, build a Resources slice via `collections.Slice` first.
  3. Ensure the template variable is not nil or a single Resource.

Example fix

// template -- before
{{ $merged := merge $resources (slice $r1 $r2) }}

// after
{{ $extra := resources.Match "img/**" }}
{{ $merged := merge $resources $extra }}
Defensive patterns

Strategy: type-guard

Type guard

func isResources(v any) bool {
	_, ok := v.(resource.Resources)
	return ok
}

Prevention

When it happens

Trigger: A template calls the `merge` resource function with a non-Resources value: a single Resource, a `[]any` of resources (rather than `Resources`), a Pages slice, nil, or a string.

Common situations: Template plumbing passing a `slice` result (which is `[]any`) into `merge` instead of `.Resources`; calling `merge` on a Page where `.Resources` was intended; upgrading Hugo where merge input typing tightened.

Related errors


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