gohugoio/hugo · error

id must not contain forward slashes

Error message

id must not contain forward slashes

What it means

ValidateBatchID forbids forward slashes in a non-top-level batch id (batch.go:161-164). Only top-level ids may contain '/'; sub-group ids (isTopLevel==false, as used by BatchGroup) must be a single path segment. This prevents sub-ids from escaping their group's namespace.

Solutions

  1. Use a single-segment id (no '/') for sub-groups; encode hierarchy via the group structure, not the id string.
  2. If you need a path-like id, use it at the top level (isTopLevel=true) or flatten it (replace '/' with '_').
  3. Validate the id with ValidateBatchID(id, false) before calling Group to get a returned error instead of a panic.

Example fix

// before
group := batcher.Group(ctx, "my/sub/group") // panics

// after
group := batcher.Group(ctx, "my_sub_group")
Defensive patterns

Strategy: validation

Validate before calling

func validateGroupID(id string) error {
    // Sub-group ids must be a single segment.
    return esbuild.ValidateBatchID(id, false)
}

Type guard

func isSingleSegmentID(id string) bool { return !strings.Contains(id, "/") }

Prevention

When it happens

Trigger: Calling Batcher.Group(ctx, "sub/path") — Group passes isTopLevel=false, so any '/' in the id triggers the error (and a panic, since Group panics on validation failure).

Common situations: Using a derived path with slashes as a sub-group id instead of a flat name; treating Group like a top-level entry point.

Related errors


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

Appendix: 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 52c9bd7908)