{"record":{"id":"e60f6d66ad39d87f","repo":"kataras/iris","slug":"err-e60f6d","errorCode":null,"errorMessage":"err","messagePattern":"err","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"view/jet.go","lineNumber":98,"sourceCode":"\t\tloader:            &jetLoader{fs: getFS(dirOrFS)},\n\t\tjetDataContextKey: \"_jet\",\n\t}\n\n\treturn s\n}\n\n// String returns the name of this view engine, the \"jet\".\nfunc (s *JetEngine) String() string {\n\treturn jetEngineName\n}\n\n// RootDir sets the directory to be used as a starting point\n// to load templates from the provided file system.\nfunc (s *JetEngine) RootDir(root string) *JetEngine {\n\tif s.fs != nil && root != \"\" && root != \"/\" && root != \".\" && root != s.rootDir {\n\t\tsub, err := fs.Sub(s.fs, s.rootDir)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\n\t\ts.fs = sub\n\t}\n\n\ts.rootDir = filepath.ToSlash(root)\n\treturn s\n}\n\n// Name returns the jet engine's name.\nfunc (s *JetEngine) Name() string {\n\treturn \"Jet\"\n}\n\n// Ext should return the final file extension which this view engine is responsible to render.\n// If the filename extension on ExecuteWriter is empty then this is appended.\nfunc (s *JetEngine) Ext() string {\n\treturn s.extension","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/view/jet.go#L80-L116","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\napp.Use(iris.New().JetEngine(iris FS{fs: embedded}).RootDir(\"tpl\")) // mismatched prefix\n// after\n// embed templates under templates/\nengine.RootDir(\"/templates\") // matches embed.FS directory","handlingStrategy":"validation","validationCode":"func validateRoot(root string) bool { return root != \"\" && root != \"/\" && root != \".\" }\n// call only if valid; otherwise configure fs via New(...FS) with correct embed prefix","typeGuard":null,"tryCatchPattern":"func safeRootDir(e *view.JetEngine, root string) (ok bool) {\n    defer func() { if r := recover(); r != nil { log.Printf(\"RootDir panic: %v\", r) } }()\n    e.RootDir(root)\n    return true\n}","preventionTips":["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"],"tags":["go","panic","templates","filesystem"],"backgroundTag":"invalid-template-root-dir","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}