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

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Ensure RootDir is called before any fs-assigning call, or with a root path consistent with the existing fs
  2. Verify the embedded FS prefix matches the root string exactly (e.g. embed.FS rooted at 'templates' -> RootDir("/templates"))
  3. 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

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.