{"record":{"id":"fe1520becd1873ad","repo":"gohugoio/hugo","slug":"invalid-module-replacements-q-configure-replace","errorCode":null,"errorMessage":"invalid module.replacements: %q; configure replacement pairs on the form \"oldpath->newpath\" ","messagePattern":"invalid module\\.replacements: %q; configure replacement pairs on the form \"oldpath->newpath\" ","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/config.go","lineNumber":212,"sourceCode":"\t\tif err := mapstructure.WeakDecode(m, &c); err != nil {\n\t\t\treturn c, err\n\t\t}\n\n\t\tif c.replacementsMap == nil {\n\n\t\t\tif len(c.Replacements) == 1 {\n\t\t\t\tc.Replacements = strings.Split(c.Replacements[0], \",\")\n\t\t\t}\n\n\t\t\tfor i, repl := range c.Replacements {\n\t\t\t\tc.Replacements[i] = strings.TrimSpace(repl)\n\t\t\t}\n\n\t\t\tc.replacementsMap = make(map[string]string)\n\t\t\tfor _, repl := range c.Replacements {\n\t\t\t\tparts := strings.Split(repl, \"->\")\n\t\t\t\tif len(parts) != 2 {\n\t\t\t\t\treturn c, fmt.Errorf(`invalid module.replacements: %q; configure replacement pairs on the form \"oldpath->newpath\" `, repl)\n\t\t\t\t}\n\n\t\t\t\tc.replacementsMap[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])\n\t\t\t}\n\t\t}\n\n\t\tif c.replacementsMap != nil && c.Imports != nil {\n\t\t\tfor i, imp := range c.Imports {\n\t\t\t\tif newImp, found := c.replacementsMap[imp.Path]; found {\n\t\t\t\t\timp.Path = newImp\n\t\t\t\t\timp.pathProjectReplaced = true\n\t\t\t\t\tc.Imports[i] = imp\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor i, mnt := range c.Mounts {\n\t\t\tmnt.Source = filepath.Clean(mnt.Source)","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/modules/config.go#L194-L230","documentation":"Raised in decodeConfig (modules/config.go:212) while parsing module.replacements. Each entry must be a single 'oldpath->newpath' pair; strings.Split on '->' must yield exactly two parts. Any entry without exactly one arrow is rejected with the offending value quoted.","triggerScenarios":"module.replacements contains an entry lacking the '->' separator (e.g. 'github.com/a/b'), using the wrong arrow ('=>', '->'), or empty string. Also when a comma-separated single string has a malformed segment.","commonSituations":"Copying a replacement example and omitting the arrow; using 'new=old' YAML-style instead of the Hugo form; trailing commas producing an empty segment; whitespace-only entries.","solutions":["Format every replacement as 'oldpath->newpath', e.g. 'github.com/a/b -> github.com/myfork/b'.","If using a single comma-separated string, ensure each comma-separated segment still contains exactly one '->'.","Remove empty or duplicate entries."],"exampleFix":"// before\n[module]\nreplacements = 'github.com/a/b'\n\n// after\n[module]\nreplacements = 'github.com/a/b -> github.com/myfork/b'","handlingStrategy":"validation","validationCode":"// validate replacements before feeding config to Hugo\nfor _, r := range cfg.Module.Replacements {\n    parts := strings.Split(r, \"->\")\n    if len(parts) != 2 || strings.TrimSpace(parts[0]) == \"\" || strings.TrimSpace(parts[1]) == \"\" {\n        return fmt.Errorf(\"invalid replacement %q; use oldpath->newpath\", r)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the exact 'oldpath -> newpath' syntax.","Prefer the TOML array form for readability.","Lint module.replacements in a config preflight."],"tags":["hugo","module-replacements","configuration"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}