{"record":{"id":"2cb025081b61fd50","repo":"gohugoio/hugo","slug":"s-q-mount-source-must-be-a-local-path-for-modu","errorCode":null,"errorMessage":"%s: %q: mount source must be a local path for modules/themes","messagePattern":"(.+?): %q: mount source must be a local path for modules/themes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/collect.go","lineNumber":819,"sourceCode":"\t\t}\n\n\t\t// Special case for node_modules imports in themes/modules.\n\t\t// See #14089.\n\t\tvar isModuleNodeModulesImport bool\n\t\tif !owner.projectMod {\n\t\t\tnodeModulesImportSource := c.nodeModulesRoot(mnt.Source)\n\t\t\tif nodeModulesImportSource != \"\" {\n\t\t\t\tisModuleNodeModulesImport = true\n\t\t\t\tmnt.Source = nodeModulesImportSource\n\t\t\t}\n\t\t}\n\n\t\tmnt.Source = filepath.Clean(mnt.Source)\n\t\tmnt.Target = filepath.Clean(mnt.Target)\n\t\tvar sourceDir string\n\n\t\tif !owner.projectMod && !filepath.IsLocal(mnt.Source) {\n\t\t\treturn nil, fmt.Errorf(\"%s: %q: mount source must be a local path for modules/themes\", errMsg, mnt.Source)\n\t\t}\n\t\tif filepath.IsAbs(mnt.Source) {\n\t\t\t// Abs paths in the main project is allowed.\n\t\t\tsourceDir = mnt.Source\n\t\t} else {\n\t\t\tsourceDir = filepath.Join(dir, mnt.Source)\n\t\t}\n\n\t\t// Verify that Source exists\n\t\t_, err := c.fs.Stat(sourceDir)\n\t\tif err != nil {\n\t\t\tif paths.IsSameFilePath(sourceDir, c.ccfg.PublishDir) {\n\t\t\t\t// This is a little exotic, but there are use cases for mounting the public folder.\n\t\t\t\t// This will typically also be in .gitingore, so create it.\n\t\t\t\tif err := c.fs.MkdirAll(sourceDir, 0o755); err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"%s: %q\", errMsg, err)\n\t\t\t\t}\n\t\t\t} else if strings.HasSuffix(sourceDir, files.FilenameHugoStatsJSON) {","sourceCodeStart":801,"sourceCodeEnd":837,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/modules/collect.go#L801-L837","documentation":"normalizeMounts enforces that mounts defined inside a theme or module (owner.projectMod false) must use a local (relative, in-tree) source — it calls filepath.IsLocal which rejects absolute paths and any path containing `..`. A non-local source from a theme/module would let it reach arbitrary filesystem locations, so it's rejected.","triggerScenarios":"A theme/module's config defines `[[module.mounts]] source = \"/abs/path\"` or `source = \"../sibling\"`. Since the owner is not the project, Hugo refuses to honour escapes; only the project itself may mount absolute/external paths.","commonSituations":"Theme author copies a project-level mount (with an absolute or `..` source) into the theme config; theme developed as a project then published without sanitising mounts; cross-theme shared assets referenced via `..`.","solutions":["In the theme/module config, make every mount source a path relative to the module root with no `..` or leading slash.","If you genuinely need an external path, declare that mount in the project's own config (project modules may use absolute paths).","Move the shared asset into the theme and reference it relatively.","Publish a corrected version of the theme with local-only mount sources."],"exampleFix":"// before (inside theme config): not local\n[[module.mounts]]\nsource = \"/home/me/shared/assets\"\ntarget = \"assets\"\n// after: keep assets inside the theme\n[[module.mounts]]\nsource = \"shared-assets\"\ntarget = \"assets\"","handlingStrategy":"validation","validationCode":"// Reject non-local mount sources in any non-project module config\nimport \"path/filepath\"\n\nfunc validateMountSources(ownerIsProject bool, mounts []Mount) error {\n  if ownerIsProject { return nil }\n  for _, m := range mounts {\n    if !filepath.IsLocal(m.Source) {\n      return fmt.Errorf(\"theme/module mount source must be local: %s\", m.Source)\n    }\n  }\n  return nil\n}","typeGuard":"null","tryCatchPattern":"// On 'mount source must be a local path', move the asset in-tree or relocate the mount to the project config.","preventionTips":["In theme/module configs use only relative, in-tree mount sources.","Keep absolute/external mounts in the project's own config.","Lint theme configs in CI for escaping mount sources."],"tags":["modules","mounts","config","security","hugo-module"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}