gohugoio/hugo · error

%T can not be transformed

Error message

%T can not be transformed

What it means

After parsing arguments, `resources.Fingerprint` type-asserts the resource argument to `resources.ResourceTransformer`. If the value at the resource position is not a transformable Resource (e.g. a string, nil, a Page, or a plain map), the assertion fails and Hugo reports the actual Go type via %T. Only resources obtained from resources.Get/GetMatch, page resources, or prior transformations implement this interface.

Source

Thrown at tpl/resources/resources.go:284

	if len(args) > 2 {
		return nil, errors.New("must not provide more arguments than Resource and hash algorithm")
	}

	var algo string
	resIdx := 0

	if len(args) == 2 {
		resIdx = 1
		var err error
		algo, err = cast.ToStringE(args[0])
		if err != nil {
			return nil, err
		}
	}

	r, ok := args[resIdx].(resources.ResourceTransformer)
	if !ok {
		return nil, fmt.Errorf("%T can not be transformed", args[resIdx])
	}

	return ns.integrityClient.Fingerprint(r, algo)
}

// Minify minifies the given Resource using the MediaType to pick the correct
// minifier.
func (ns *Namespace) Minify(r resources.ResourceTransformer) (resource.Resource, error) {
	return ns.minifyClient.Minify(r)
}

// PostProcess processes r after the build.
//
// Deprecated: Use templates.Defer instead.
func (ns *Namespace) PostProcess(r resource.Resource) (postpub.PostPublishedResource, error) {
	hugo.DeprecateWithLogger("resources.PostProcess", "Use templates.Defer instead. See https://gohugo.io/functions/templates/defer/", "v0.164.0", ns.deps.Log.Logger())
	return ns.deps.ResourceSpec.PostProcess(r)
}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Pass a real Resource: `{{ $css := resources.Get "css/style.css" }}{{ $fp := resources.Fingerprint $css }}`.
  2. Guard against missing assets: `{{ with resources.Get "css/style.css" }}{{ $fp := . | fingerprint }}{{ end }}` — resources.Get returns nil if the file isn't in assets/.
  3. Check argument order — the algorithm string comes first, the Resource last: `resources.Fingerprint "sha256" $res`.
  4. Move the file from static/ to assets/ if you intended it to be part of the asset pipeline.

Example fix

<!-- before -->
{{ $fp := resources.Fingerprint "css/style.css" }}
<!-- after -->
{{ with resources.Get "css/style.css" }}
  {{ $fp := resources.Fingerprint . }}
{{ end }}
Defensive patterns

Strategy: type-guard

Validate before calling

{{ $r := resources.Get "styles.scss" }}
{{ if $r }}{{ with $r | resources.Minify }}...{{ end }}{{ end }}

Type guard

{{/* ensure the value is a transformable Resource, not a string/Page */}}
{{ define "partials/is-resource.html" }}
{{ return (and . (reflect.IsMap . | not) (isset . "RelPermalink")) }}
{{ end }}

Prevention

When it happens

Trigger: `{{ resources.Fingerprint "style.css" }}` (passing a path string instead of a Resource), passing the result of `resources.Get` when the file wasn't found (nil), or swapping argument order so the algorithm string lands in the resource slot: `{{ resources.Fingerprint $res "sha512" }}`.

Common situations: resources.Get returning nil because the asset path doesn't exist under assets/ (common after moving files from static/ to assets/), argument-order mistakes when adding an algorithm, or passing a Page/string from theme code that expected a different function signature.

Related errors


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