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
- Use a single-segment id (no '/') for sub-groups; encode hierarchy via the group structure, not the id string.
- If you need a path-like id, use it at the top level (isTopLevel=true) or flatten it (replace '/' with '_').
- 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
- Use flat names for sub-group ids; encode hierarchy with separators like '_'.
- Call ValidateBatchID(id, false) before Group to get an error instead of a panic.
- Reserve '/' for top-level ids only.
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
- id must be set
- id must not contain backslashes
- failed to build JS batch
- failed to build JS batch
- only esm format is currently supported
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)