{"id":"fb1ba500edbee3b0","repo":"gohugoio/hugo","slug":"id-must-not-contain-forward-slashes","errorCode":null,"errorMessage":"id must not contain forward slashes","messagePattern":"id must not contain forward slashes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/esbuild/batch.go","lineNumber":163,"sourceCode":"\to.compiledPrev = o.compiled\n\to.compiled, o.compileErr = o.compiled.compileOptions(m, o.defaults)\n\to.checkCompileErr()\n\treturn \"\"\n}\n\n// ValidateBatchID validates the given ID according to some very\nfunc ValidateBatchID(id string, isTopLevel bool) error {\n\tif id == \"\" {\n\t\treturn fmt.Errorf(\"id must be set\")\n\t}\n\t// No Windows slashes.\n\tif strings.Contains(id, \"\\\\\") {\n\t\treturn fmt.Errorf(\"id must not contain backslashes\")\n\t}\n\n\t// Allow forward slashes in top level IDs only.\n\tif !isTopLevel && strings.Contains(id, \"/\") {\n\t\treturn fmt.Errorf(\"id must not contain forward slashes\")\n\t}\n\n\treturn nil\n}\n\nfunc newIsBuiltOrTouched() isBuiltOrTouched {\n\treturn isBuiltOrTouched{\n\t\tbuilt:   make(buildIDs),\n\t\ttouched: make(buildIDs),\n\t}\n}\n\nfunc newOpts[K any, C optionsCompiler[C]](key K, optionsID string, defaults defaultOptionValues) *opts[K, C] {\n\treturn &opts[K, C]{\n\t\tkey: key,\n\t\th: &optsHolder[C]{\n\t\t\toptionsID:        optionsID,\n\t\t\tdefaults:         defaults,","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/internal/js/esbuild/batch.go#L145-L181","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rename the group/script/instance ID to a flat identifier without '/', e.g. \"components-nav\" instead of \"components/nav\".","If you need a path-like namespace, put the slashes only in the top-level js.Batch ID and keep child IDs flat.","When deriving IDs from paths, replace slashes: {{ $id := replace .Path \"/\" \"-\" }}."],"exampleFix":"// before\n{{ $group := $batch.Group \"admin/dashboard\" }}\n// after\n{{ $group := $batch.Group \"admin-dashboard\" }}","handlingStrategy":"validation","validationCode":"if strings.Contains(id, \"/\") {\n    return fmt.Errorf(\"invalid batch id %q: forward slashes not allowed\", id)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate js.Batch identifiers at the point you construct them, before passing to the API","Use a sanitizer (e.g. replace '/' with '-') when deriving ids from paths or slugs","Add a template-level check when ids come from front matter or user content"],"tags":["hugo","esbuild","js-batch","validation","templates"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}