gohugoio/hugo · error

inject: absolute paths not supported, must be relative to /a

Error message

inject: absolute paths not supported, must be relative to /assets

What it means

The js.Build option `inject` lets you prepend files to the esbuild bundle (e.g. shims). Hugo resolves inject entries through its /assets component filesystem, so each entry must be a path relative to /assets. Absolute filesystem paths are rejected because they would bypass Hugo's virtual filesystem and module mounts.

Source

Thrown at internal/js/esbuild/build.go:87

		return api.BuildResult{}, err
	}

	if err := opts.compile(); err != nil {
		return api.BuildResult{}, err
	}

	var err error
	opts.compiled.Plugins, err = createBuildPlugins(c.rs, assetsResolver, dependencyManager, opts)
	if err != nil {
		return api.BuildResult{}, err
	}

	if opts.Inject != nil {
		// Resolve the absolute filenames.
		for i, ext := range opts.Inject {
			impPath := filepath.FromSlash(ext)
			if filepath.IsAbs(impPath) {
				return api.BuildResult{}, fmt.Errorf("inject: absolute paths not supported, must be relative to /assets")
			}

			m := assetsResolver.resolveComponent(impPath, false)

			if m == nil {
				return api.BuildResult{}, fmt.Errorf("inject: file %q not found", ext)
			}

			opts.Inject[i] = m.Filename

		}

		opts.compiled.Inject = opts.Inject

	}

	result := api.Build(opts.compiled)

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Make the inject path relative to the assets directory: use `"shims/process.js"` for assets/shims/process.js — no leading slash.
  2. Move the file to be injected into /assets (or a mounted assets dir) if it lives elsewhere.
  3. If the file comes from a Hugo module, mount it into assets/ and reference the mounted relative path.

Example fix

{{/* before */}}
{{ $js := resources.Get "main.js" | js.Build (dict "inject" (slice "/assets/shims/process.js")) }}
{{/* after */}}
{{ $js := resources.Get "main.js" | js.Build (dict "inject" (slice "shims/process.js")) }}
Defensive patterns

Strategy: validation

Validate before calling

for _, inj := range opts.Inject {
    if path.IsAbs(inj) {
        return fmt.Errorf("inject path %q must be relative to /assets", inj)
    }
}

Prevention

When it happens

Trigger: Calling `js.Build` (or `js.Batch`) with `inject` containing an absolute path, e.g. `dict "inject" (slice "/home/me/shim.js")` or a leading-slash path — filepath.IsAbs on the entry returns true and the build aborts before esbuild runs.

Common situations: Copying esbuild's own `--inject` docs, which use real filesystem paths; prefixing the entry with a slash thinking it means 'assets root' (on Linux/macOS a leading `/` is absolute); passing paths produced by `.Filename` from a resource.

Related errors


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