{"record":{"id":"da5518274d8d085e","repo":"gohugoio/hugo","slug":"id-must-not-contain-backslashes","errorCode":null,"errorMessage":"id must not contain backslashes","messagePattern":"id must not contain backslashes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/esbuild/batch.go","lineNumber":158,"sourceCode":"\nfunc (o *optsHolder[C]) SetOptions(m map[string]any) string {\n\to.optsSetCounter++\n\to.optsPrev = o.optsCurr\n\to.optsCurr = m\n\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] {","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/internal/js/esbuild/batch.go#L140-L176","documentation":"ValidateBatchID forbids backslashes in a batch id (batch.go:157-158) because backslashes conflict with path handling and virtual import resolution on Windows and produce ambiguous keys. Any id containing '\\' is rejected.","triggerScenarios":"Passing a Windows-style path (e.g. \"assets\\\\scripts\\\\main\") as a batch id; a string built with backslash separators instead of forward slashes.","commonSituations":"Code running on Windows that joins paths with filepath.Join (backslash separator) and passes the result as a batch id; copy-pasting a Windows path literal.","solutions":["Build ids with forward slashes only (use path.Join, not filepath.Join, for virtual ids).","Sanitize existing strings: replace '\\' with '/' before use.","Prefer Hugo's paths helpers which normalize separators."],"exampleFix":"// before (Windows)\nid := filepath.Join(\"assets\", \"main\") // \"assets\\main\"\n\n// after\nid := path.Join(\"assets\", \"main\") // \"assets/main\"","handlingStrategy":"validation","validationCode":"func sanitizeBatchID(id string) (string, error) {\n    if strings.Contains(id, \"\\\\\") {\n        return \"\", fmt.Errorf(\"id must not contain backslashes\")\n    }\n    return id, nil\n}\n\n// Or normalize: strings.ReplaceAll(id, \"\\\\\", \"/\")","typeGuard":"func hasNoBackslashes(id string) bool { return !strings.Contains(id, \"\\\\\") }","tryCatchPattern":null,"preventionTips":["Use path.Join (forward slashes) for virtual ids, not filepath.Join.","Sanitize Windows-derived strings before passing as ids.","Prefer Hugo's paths helpers for consistent normalization."],"tags":["esbuild","batch","js","paths","cross-platform"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}