kataras/iris · error
err
Error message
err
What it means
RootDir calls fs.Sub(s.fs, s.rootDir) to re-root the engine's embedded filesystem and panics with the raw error if fs.Sub fails. fs.Sub returns an error when the current fs is nil-ish or the dir argument is invalid relative to it, so a bad root directory breaks template loading at engine setup time.
Source
Thrown at view/jet.go:98
loader: &jetLoader{fs: getFS(dirOrFS)},
jetDataContextKey: "_jet",
}
return s
}
// String returns the name of this view engine, the "jet".
func (s *JetEngine) String() string {
return jetEngineName
}
// RootDir sets the directory to be used as a starting point
// to load templates from the provided file system.
func (s *JetEngine) RootDir(root string) *JetEngine {
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
}
s.rootDir = filepath.ToSlash(root)
return s
}
// Name returns the jet engine's name.
func (s *JetEngine) Name() string {
return "Jet"
}
// Ext should return the final file extension which this view engine is responsible to render.
// If the filename extension on ExecuteWriter is empty then this is appended.
func (s *JetEngine) Ext() string {
return s.extensionView on GitHub (pinned to 7bedaf55a0)
Solutions
- Ensure RootDir is called before any fs-assigning call, or with a root path consistent with the existing fs
- Verify the embedded FS prefix matches the root string exactly (e.g. embed.FS rooted at 'templates' -> RootDir("/templates"))
- Wrap engine setup in a recover to surface the fs.Sub error clearly during startup
Example fix
// before
app.Use(iris.New().JetEngine(iris FS{fs: embedded}).RootDir("tpl")) // mismatched prefix
// after
// embed templates under templates/
engine.RootDir("/templates") // matches embed.FS directory Defensive patterns
Strategy: validation
Validate before calling
func validateRoot(root string) bool { return root != "" && root != "/" && root != "." }
// call only if valid; otherwise configure fs via New(...FS) with correct embed prefix Try / catch
func safeRootDir(e *view.JetEngine, root string) (ok bool) {
defer func() { if r := recover(); r != nil { log.Printf("RootDir panic: %v", r) } }()
e.RootDir(root)
return true
} Prevention
- Set RootDir before assigning any filesystem so fs.Sub never runs on an inconsistent state
- Match the root string to the embed.FS directory prefix exactly
- Start the app in a startup-time recover that logs panics from engine configuration
When it happens
Trigger: Calling RootDir with a root that is invalid for the previously set fs (e.g. fs was already sub-rooted, or rootDir/fs state is inconsistent so fs.Sub cannot resolve the path), after an fs was set via New/Embed/FS.
Common situations: Embedding templates with embed.FS and then calling RootDir with a path that doesn't match the embed prefix; calling RootDir twice with different roots after an fs was assigned.
Related errors
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/e60f6d66ad39d87f.
Report an issue: GitHub.