{"record":{"id":"0f581147a5df9aea","repo":"kataras/iris","slug":"err-0f5811","errorCode":null,"errorMessage":"err","messagePattern":"err","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"view/django.go","lineNumber":140,"sourceCode":"\ts := &DjangoEngine{\n\t\tfs:            getFS(fs),\n\t\trootDir:       \"/\",\n\t\textension:     extension,\n\t\tglobals:       make(map[string]any),\n\t\tfilters:       make(map[string]FilterFunction),\n\t\ttemplateCache: make(map[string]*pongo2.Template),\n\t}\n\n\treturn s\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 *DjangoEngine) RootDir(root string) *DjangoEngine {\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 // here so the \"middleware\" can work.\n\t}\n\n\ts.rootDir = filepath.ToSlash(root)\n\treturn s\n}\n\n// Name returns the django engine's name.\nfunc (s *DjangoEngine) Name() string {\n\treturn \"Django\"\n}\n\n// Ext returns the 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 *DjangoEngine) Ext() string {\n\treturn s.extension","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/view/django.go#L122-L158","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\neng := view.Django(view.FS(templateFS))\neng.RootDir(\"views\") // panics: \"views\" not at FS root (it's under templates/)\n// after\neng := view.Django(view.FS(templateFS), \"templates/views\")","handlingStrategy":"validation","validationCode":"if _, err := fs.Stat(engineFS, \"views\"); err != nil {\n\tlog.Fatalf(\"template root missing: %v\", err)\n}\nengine.RootDir(\"views\")","typeGuard":null,"tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tlog.Fatalf(\"RootDir failed: %v\", r)\n\t}\n}()","preventionTips":["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."],"tags":["templates","filesystem","panic","embedded-fs"],"backgroundTag":"template-root-not-found","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}