{"record":{"id":"6a5dec94d920c1cf","repo":"gohugoio/hugo","slug":"alias-s-resolves-to-website-root-directory","errorCode":null,"errorMessage":"alias \"%s\" resolves to website root directory","messagePattern":"alias \"(.+?)\" resolves to website root directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"hugolib/alias.go","lineNumber":132,"sourceCode":"\t}\n\n\tif s.conf.RelativeURLs || s.conf.CanonifyURLs {\n\t\tpd.AbsURLPath = s.absURLPath(targetPath)\n\t}\n\n\treturn s.publisher.Publish(pd)\n}\n\nfunc (a aliasHandler) targetPathAlias(src string, of output.Format) (string, error) {\n\toriginalAlias := src\n\tif len(src) <= 0 {\n\t\treturn \"\", fmt.Errorf(\"alias \\\"\\\" is an empty string\")\n\t}\n\n\talias := path.Clean(filepath.ToSlash(src))\n\n\tif !a.allowRoot && alias == \"/\" {\n\t\treturn \"\", fmt.Errorf(\"alias \\\"%s\\\" resolves to website root directory\", originalAlias)\n\t}\n\n\tcomponents := strings.Split(alias, \"/\")\n\n\t// Validate against directory traversal\n\tif components[0] == \"..\" {\n\t\treturn \"\", fmt.Errorf(\"alias \\\"%s\\\" traverses outside the website root directory\", originalAlias)\n\t}\n\n\t// Handle Windows file and directory naming restrictions\n\t// See \"Naming Files, Paths, and Namespaces\" on MSDN\n\t// https://msdn.microsoft.com/en-us/library/aa365247%28v=VS.85%29.aspx?f=255&MSPPError=-2147217396\n\tmsgs := []string{}\n\treservedNames := []string{\"CON\", \"PRN\", \"AUX\", \"NUL\", \"COM0\", \"COM1\", \"COM2\", \"COM3\", \"COM4\", \"COM5\", \"COM6\", \"COM7\", \"COM8\", \"COM9\", \"LPT0\", \"LPT1\", \"LPT2\", \"LPT3\", \"LPT4\", \"LPT5\", \"LPT6\", \"LPT7\", \"LPT8\", \"LPT9\"}\n\n\tif strings.ContainsAny(alias, \":*?\\\"<>|\") {\n\t\tmsgs = append(msgs, fmt.Sprintf(\"Alias \\\"%s\\\" contains invalid characters on Windows: : * ? \\\" < > |\", originalAlias))\n\t}","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/hugolib/alias.go#L114-L150","documentation":"Returned by targetPathAlias when path.Clean of the alias equals \"/\" (the website root) and the aliasHandler was constructed with allowRoot=false. Writing an alias over the site root would clobber index.html, so it is blocked. The publishDestAlias entry point (used for page aliases) passes allowRoot=false; publishDestAliasWithAllowRoot may pass true.","triggerScenarios":"A page front-matter aliases entry that is exactly \"/\" or collapses to it (e.g. \"./\" , \"//\"). Triggered during site publish when Hugo renders redirect pages for each alias.","commonSituations":"Author mistakenly sets aliases: [\"/\"] thinking it redirects to the homepage; a templated alias built from a path variable that becomes root; importing content from another SSG whose root alias semantics differ.","solutions":["Remove the \"/\" alias from the page's front matter; use a distinct path like \"/home/\" or \"/index-alias/\".","If a root alias is genuinely intended (rare), use the internal API path that sets allowRoot=true, but note this overwrites the homepage redirect.","Lint front matter to reject aliases that path.Clean to \"/\"."],"exampleFix":"---\n# before\naliases:\n  - \"/\"\n# after\naliases:\n  - \"/old-home/\"\n---","handlingStrategy":"validation","validationCode":"func cleanAlias(a string) (string, error) {\n    c := path.Clean(filepath.ToSlash(a))\n    if c == \"/\" { return \"\", fmt.Errorf(\"alias resolves to root\") }\n    return c, nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid aliases: [\"/\"]; use a distinct subpath.","Sanitize generated aliases so they never path.Clean to \"/\".","Review imported/redirect content for root aliases."],"tags":["alias","front-matter","path-traversal","hugolib"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}