kataras/iris · error
err
Error message
err
What it means
DjangoEngine.RootDir re-bases the engine's embedded filesystem with fs.Sub(s.fs, s.rootDir) when a new root is set on an already-initialized FS. If the embedded FS cannot be rooted at that path (path missing or invalid), fs.Sub returns an error and the engine panics, since a view engine without a usable template root cannot render anything.
Source
Thrown at view/django.go:140
s := &DjangoEngine{
fs: getFS(fs),
rootDir: "/",
extension: extension,
globals: make(map[string]any),
filters: make(map[string]FilterFunction),
templateCache: make(map[string]*pongo2.Template),
}
return s
}
// RootDir sets the directory to be used as a starting point
// to load templates from the provided file system.
func (s *DjangoEngine) RootDir(root string) *DjangoEngine {
if s.fs != nil && root != "" && root != "/" && root != "." && root != s.rootDir {
sub, err := fs.Sub(s.fs, s.rootDir)
if err != nil {
panic(err)
}
s.fs = sub // here so the "middleware" can work.
}
s.rootDir = filepath.ToSlash(root)
return s
}
// Name returns the django engine's name.
func (s *DjangoEngine) Name() string {
return "Django"
}
// Ext returns the file extension which this view engine is responsible to render.
// If the filename extension on ExecuteWriter is empty then this is appended.
func (s *DjangoEngine) Ext() string {
return s.extensionView on GitHub (pinned to 7bedaf55a0)
Solutions
- Ensure the path given to RootDir exists inside the filesystem the engine was constructed with (remember embed.FS paths exclude the module directory prefix).
- Set the root once at construction: view.Django(view.FS(embedded), "templates") instead of calling RootDir afterwards.
- If chaining, make the second RootDir consistent with the first (root == s.rootDir short-circuits the fs.Sub call).
- Walk the FS (fs.WalkDir) before calling RootDir to verify the subdirectory exists.
Example fix
// before
eng := view.Django(view.FS(templateFS))
eng.RootDir("views") // panics: "views" not at FS root (it's under templates/)
// after
eng := view.Django(view.FS(templateFS), "templates/views") Defensive patterns
Strategy: validation
Validate before calling
if _, err := fs.Stat(engineFS, "views"); err != nil {
log.Fatalf("template root missing: %v", err)
}
engine.RootDir("views") Try / catch
defer func() {
if r := recover(); r != nil {
log.Fatalf("RootDir failed: %v", r)
}
}() Prevention
- Pass the root at engine construction instead of post-hoc RootDir.
- Remember embed.FS paths exclude the source directory prefix.
- Unit-test template loading at startup.
When it happens
Trigger: Calling d.RootDir("some/path") on a Django engine whose fs was already created (via New/Django(...)) where s.rootDir points to a directory that does not exist inside the embedded/embed.FS or fs.FS.
Common situations: embed.FS built with //go:embed templates where the developer passes RootDir("views") but the FS root contains "templates/views", or chaining RootDir twice with mismatched roots.
Related errors
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/0f581147a5df9aea.
Report an issue: GitHub.