{"record":{"id":"11ad8583d7798002","repo":"gohugoio/hugo","slug":"q-is-not-a-directory","errorCode":null,"errorMessage":"%q is not a directory","messagePattern":"%q is not a directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/hugio/copy.go","lineNumber":61,"sourceCode":"\t\terr = fs.Chmod(to, si.Mode())\n\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// CopyDir copies a directory.\nfunc CopyDir(fs afero.Fs, from, to string, shouldCopy func(filename string) bool) error {\n\tfi, err := fs.Stat(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !fi.IsDir() {\n\t\treturn fmt.Errorf(\"%q is not a directory\", from)\n\t}\n\n\terr = fs.MkdirAll(to, 0o777) // before umask\n\tif err != nil {\n\t\treturn err\n\t}\n\n\td, err := fs.Open(from)\n\tif err != nil {\n\t\treturn err\n\t}\n\tentries, _ := d.(iofs.ReadDirFile).ReadDir(-1)\n\tfor _, entry := range entries {\n\t\tfromFilename := filepath.Join(from, entry.Name())\n\t\ttoFilename := filepath.Join(to, entry.Name())\n\t\tif entry.IsDir() {\n\t\t\tif shouldCopy != nil && !shouldCopy(fromFilename) {\n\t\t\t\tcontinue","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/common/hugio/copy.go#L43-L79","documentation":"Returned by hugio.CopyDir when the source path exists but fs.Stat reports it as a file rather than a directory. CopyDir walks entries via ReadDir, so a non-directory source is an unrecoverable precondition violation.","triggerScenarios":"Calling hugio.CopyDir(fs, from, to, shouldCopy) where `from` resolves to a regular file, a symlink to a file, or a special file.","commonSituations":"Theme/static-file copying during `hugo` builds when a configured directory (e.g. `staticDir`, `assetDir`) actually points at a single file; or recursive walks where a symlink unexpectedly resolves to a file.","solutions":["Point `from` at an actual directory.","If only a single file needs copying, use hugio.CopyFile instead.","Resolve symlinks before calling and verify os.Stat.IsDir()."],"exampleFix":"// before\nhugio.CopyDir(fs, \"content/post.md\", \"public/post.md\", nil)\n// after\nhugio.CopyFile(fs, \"content/post.md\", \"public/post.md\")","handlingStrategy":"validation","validationCode":"func ensureDir(fs afero.Fs, p string) error {\n  info, err := fs.Stat(p)\n  if err != nil { return err }\n  if !info.IsDir() { return fmt.Errorf(\"%q is not a directory\", p) }\n  return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify fs.Stat(...).IsDir() before CopyDir.","Use CopyFile for single files.","Resolve symlinks before stat."],"tags":["hugio","copy","directory","filesystem"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}