{"record":{"id":"a9d3b805bd873004","repo":"gohugoio/hugo","slug":"s-mount-target-must-be-one-of-v","errorCode":null,"errorMessage":"%s: mount target must be one of: %v","messagePattern":"(.+?): mount target must be one of: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/collect.go","lineNumber":871,"sourceCode":"\t\t\t\t\t_, err := c.fs.Stat(sourceDir)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tmnt.Source = sourceDir\n\t\t\t\t} else {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Verify that target points to one of the predefined component dirs\n\t\ttargetBase := mnt.Target\n\t\tidxPathSep := strings.Index(mnt.Target, string(os.PathSeparator))\n\t\tif idxPathSep != -1 {\n\t\t\ttargetBase = mnt.Target[0:idxPathSep]\n\t\t}\n\t\tif !files.IsComponentFolder(targetBase) {\n\t\t\treturn nil, fmt.Errorf(\"%s: mount target must be one of: %v\", errMsg, files.ComponentFolders)\n\t\t}\n\n\t\tif err := mnt.init(c.logger.Logger()); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%s: %w\", errMsg, err)\n\t\t}\n\n\t\tout = append(out, mnt)\n\t}\n\n\treturn out, nil\n}\n\nfunc (c *collector) wrapModuleNotFound(err error) error {\n\tif c.Client.ccfg.IgnoreModuleDoesNotExist {\n\t\treturn nil\n\t}\n\terr = fmt.Errorf(err.Error()+\": %w\", ErrNotExist)\n\tif c.GoModulesFilename == \"\" {","sourceCodeStart":853,"sourceCodeEnd":889,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/modules/collect.go#L853-L889","documentation":"Thrown by normalizeMounts (modules/collect.go:871) while validating every mount of a module/theme. The first path segment of the mount's 'target' is checked against files.ComponentFolders (archetypes, assets, content, data, i18n, layouts, static); anything else is rejected because Hugo only knows how to route content into those component trees.","triggerScenarios":"A [[module.mounts]] entry sets target to a non-component base, e.g. target=\"css\", target=\"myfolder\", or target=\"public\". Also fires when source and target are swapped, putting the filesystem path into target.","commonSituations":"Typo such as 'asset' instead of 'assets'; assuming target can be any directory; mounting CSS/JS directly to 'css'/'js' instead of nesting under 'assets'; copying a mount example from a tutorial using outdated target names.","solutions":["Set target to start with a valid component folder. For frontend assets use target=\"assets/css\" (or \"assets/js\"), not \"css\".","Verify source and target are not swapped: source is the real on-disk path, target is the Hugo-internal component location.","If you need a custom output location, that is configured elsewhere (output formats / publishDir), not via mount target."],"exampleFix":"// before\n[[module.mounts]]\nsource = \"src/css\"\ntarget = \"css\"\n\n// after\n[[module.mounts]]\nsource = \"src/css\"\ntarget = \"assets/css\"","handlingStrategy":"validation","validationCode":"// validate mounts before/when configuring Hugo\nallowed := map[string]bool{\"archetypes\":true,\"assets\":true,\"content\":true,\"data\":true,\"i18n\":true,\"layouts\":true,\"static\":true}\nfor _, m := range cfg.Module.Mounts {\n    base := strings.SplitN(filepath.ToSlash(filepath.Clean(m.Target)), \"/\", 2)[0]\n    if !allowed[base] {\n        return fmt.Errorf(\"mount target %q must start with one of %v\", m.Target, maps.Keys(allowed))\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always nest custom targets under a valid component folder (e.g. assets/css).","Treat target as a Hugo-internal path, not a filesystem path.","Lint your config with a schema/validator before building."],"tags":["hugo","module-mounts","configuration"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}