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.extension

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Ensure the path given to RootDir exists inside the filesystem the engine was constructed with (remember embed.FS paths exclude the module directory prefix).
  2. Set the root once at construction: view.Django(view.FS(embedded), "templates") instead of calling RootDir afterwards.
  3. If chaining, make the second RootDir consistent with the first (root == s.rootDir short-circuits the fs.Sub call).
  4. 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

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.