caddyserver/caddy · error
%v is not a directory
Error message
%v is not a directory
What it means
Returned by the templates module's listFiles function when the path given exists and was opened successfully but is not a directory (stat.IsDir() is false). The function then cannot Readdir it.
Source
Thrown at modules/caddyhttp/templates/tplcontext.go:409
// funcListFiles reads and returns a slice of names from the given
// directory relative to the root of c.
func (c TemplateContext) funcListFiles(name string) ([]string, error) {
if c.Root == nil {
return nil, fmt.Errorf("root file system not specified")
}
dir, err := c.Root.Open(path.Clean(name))
if err != nil {
return nil, err
}
defer dir.Close()
stat, err := dir.Stat()
if err != nil {
return nil, err
}
if !stat.IsDir() {
return nil, fmt.Errorf("%v is not a directory", name)
}
dirInfo, err := dir.Readdir(0)
if err != nil {
return nil, err
}
names := make([]string, len(dirInfo))
for i, fileInfo := range dirInfo {
names[i] = fileInfo.Name()
}
return names, nil
}
// funcFileExists returns true if filename can be opened successfully.
func (c TemplateContext) funcFileExists(filename string) (bool, error) {
if c.Root == nil {View on GitHub (pinned to 50e54ee279)
Solutions
- Point listFiles at a directory, e.g. {{ listFiles "/posts" }} or use path.Dir of the file
- Guard with {{ if (stat .).IsDir }} style checks or split files vs dirs before calling
- Log or render the offending path temporarily to see what the placeholder resolves to
- Trim trailing filenames from computed paths in the template
Example fix
<!-- before -->
{{ listFiles "/posts/2024/post.md" }}
<!-- after -->
{{ listFiles "/posts/2024" }} Defensive patterns
Strategy: type-guard
Type guard
{{ $s := stat "/posts/2024" }}{{ if $s.IsDir }}{{ listFiles "/posts/2024" }}{{ else }}not a directory{{ end }} Prevention
- Always stat-check before listFiles when the path is dynamic
- Derive directories with path.Dir rather than trusting raw variables
- Render candidate paths during development to verify they point at folders
When it happens
Trigger: {{ listFiles "notes.txt" }} where notes.txt is a regular file; or a dynamic path built from a placeholder that resolves to a file name instead of a folder.
Common situations: Passing a file path where a directory was intended, using '.' on a root that maps to a single file, or template logic like {{ listFiles .Path }} where .Path points at an article file rather than its containing directory.
Related errors
- root file system not specified
- no traversable path
- [%s] invalid array index '%s': %v
- [/%s] invalid array index '%s': %v
- invalid traversal path at: %s
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/7ec4aa12e156a4c9.
Report an issue: GitHub.