gohugoio/hugo · error
could not determine content directory for
Error message
could not determine content directory for %q
What it means
Returned by BaseFs content-directory resolution when no project content mount can host the given filename. Hugo tries every content mount: absolute paths must match a mount's BaseDir/Filename, relative paths go into the first project content directory. If none qualifies, it gives up with this error.
Solutions
- Inspect the %q filename in the message and compare it against your [[mounts]] source/target in hugo config — the absolute path must be inside a mount's source.
- Add or fix a content mount so the offending path is covered: target = "content", source = "<dir-containing-the-file>".
- If the path is correct, ensure the mount is marked as a project mount and the directory exists.
- Avoid passing absolute paths that are not under any module/project root.
Example fix
// before [[mounts]] source = "/srv/site/pages" target = "content" // file at /srv/site/posts/x.md -> no match (outside /srv/site/pages) // after: make the mount cover the real content root [[mounts]] source = "/srv/site" target = "content"
Defensive patterns
Strategy: validation
Validate before calling
// Validate before resolving: ensure an absolute path is under a content mount.
func underContentMount(absPath string, mounts []Mount) bool {
for _, m := range mounts {
if m.Target == "content" && strings.HasPrefix(absPath, m.Source) {
return true
}
}
return false
} Try / catch
rel, abs, err := b.Paths().FilenameFromBase(filename)
if err != nil {
// surface the unresolvable path and skip/abort
h.Log.Errorf("content resolution: %v", err)
return
} Prevention
- Always pass paths relative to a content mount unless you control the mounts.
- Audit [[mounts]] source/target pairs whenever restructuring the repo.
- Add a CI check that every content file resolves to a mount.
When it happens
Trigger: Raised when resolving where to place a content file whose absolute path does not fall under any configured content mount (no mount's Filename/BaseDir prefix matches), and the path is absolute so the 'first project dir' fallback is skipped.
Common situations: Misconfigured module mounts where source paths don't align with the actual filesystem layout; an absolute path passed from a tool/plugin that lives outside all mounted content roots; theme/content mount `source` pointing at the wrong directory after a repo restructure.
Related errors
- build filesystems
- cannot vendor module
- create main fs
- failed to apply mounts for project
- failed to create workingDir
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/b4dfcd3fc423140d.
Report an issue: GitHub.
Appendix: source
Thrown at hugolib/filesystems/basefs.go:210
}
if !isAbs {
// A filename on the form "posts/mypage.md", put it inside
// the first content folder, usually <workDir>/content.
// Pick the first project dir (which is probably the most important one).
for _, dir := range b.SourceFilesystems.Content.mounts() {
if !dir.IsDir() {
continue
}
meta := dir.Meta()
if meta.IsProject {
return filename, filepath.Join(meta.Filename, filename), nil
}
}
}
return "", "", fmt.Errorf("could not determine content directory for %q", filename)
}
// ResolveJSConfigFile resolves the JS-related config file to a absolute
// filename. One example of such would be postcss.config.js.
func (b *BaseFs) ResolveJSConfigFile(name string) string {
// First look in assets/_jsconfig
fi, err := b.Assets.Fs.Stat(filepath.Join(files.FolderJSConfig, name))
if err == nil {
return fi.(hugofs.FileMetaInfo).Meta().Filename
}
// Fall back to the work dir.
fi, err = b.Work.Stat(name)
if err == nil {
return fi.(hugofs.FileMetaInfo).Meta().Filename
}
return ""
}View on GitHub (pinned to 52c9bd7908)