gohugoio/hugo · error

id must not contain forward slashes

Error message

id must not contain forward slashes

What it means

Returned by ValidateBatchID in Hugo's esbuild JS batching support (internal/js/esbuild/batch.go:162). Batch script/group/instance IDs become part of generated file paths and import identifiers, so only top-level batch IDs may contain '/'; nested IDs (groups, scripts within a group) must be flat single-segment names. A separate check also rejects backslashes in all IDs.

Source

Thrown at internal/js/esbuild/batch.go:163

	o.compiledPrev = o.compiled
	o.compiled, o.compileErr = o.compiled.compileOptions(m, o.defaults)
	o.checkCompileErr()
	return ""
}

// ValidateBatchID validates the given ID according to some very
func ValidateBatchID(id string, isTopLevel bool) error {
	if id == "" {
		return fmt.Errorf("id must be set")
	}
	// No Windows slashes.
	if strings.Contains(id, "\\") {
		return fmt.Errorf("id must not contain backslashes")
	}

	// Allow forward slashes in top level IDs only.
	if !isTopLevel && strings.Contains(id, "/") {
		return fmt.Errorf("id must not contain forward slashes")
	}

	return nil
}

func newIsBuiltOrTouched() isBuiltOrTouched {
	return isBuiltOrTouched{
		built:   make(buildIDs),
		touched: make(buildIDs),
	}
}

func newOpts[K any, C optionsCompiler[C]](key K, optionsID string, defaults defaultOptionValues) *opts[K, C] {
	return &opts[K, C]{
		key: key,
		h: &optsHolder[C]{
			optionsID:        optionsID,
			defaults:         defaults,

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Rename the group/script/instance ID to a flat identifier without '/', e.g. "components-nav" instead of "components/nav".
  2. If you need a path-like namespace, put the slashes only in the top-level js.Batch ID and keep child IDs flat.
  3. When deriving IDs from paths, replace slashes: {{ $id := replace .Path "/" "-" }}.

Example fix

// before
{{ $group := $batch.Group "admin/dashboard" }}
// after
{{ $group := $batch.Group "admin-dashboard" }}
Defensive patterns

Strategy: validation

Validate before calling

if strings.Contains(id, "/") {
    return fmt.Errorf("invalid batch id %q: forward slashes not allowed", id)
}

Prevention

When it happens

Trigger: Calling js.Batch group/script/instance/runner/config methods in templates with an ID like "my/script" for a non-top-level element, e.g. {{ $group := $batch.Group "admin/ui" }} or {{ $group.Script "foo/bar" }}. Only the batch itself (js.Batch "js/mybatch") accepts slashes.

Common situations: Developers mirror file paths in script IDs ("components/nav") when defining js.Batch groups or scripts; copying the top-level batch ID pattern (which does allow slashes) down to group/script IDs; templating IDs from page paths without sanitizing.

Related errors


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