{"record":{"id":"5b41ec20473499bd","repo":"twigphp/Twig","slug":"template-s-does-not-exist","errorCode":null,"errorMessage":"Template \"%s\" does not exist.","messagePattern":"Template \"(.+?)\" does not exist\\.","errorType":"exception","errorClass":"Twig\\Error\\LoaderError","httpStatus":null,"severity":"error","filePath":"doc/recipes.rst","lineNumber":426,"sourceCode":"\nWe have created a simple ``templates`` table that hosts two templates:\n``base.html.twig`` and ``index.html.twig``.\n\nNow, let's define a loader able to use this database::\n\n    class DatabaseTwigLoader implements \\Twig\\Loader\\LoaderInterface\n    {\n        protected $dbh;\n\n        public function __construct(PDO $dbh)\n        {\n            $this->dbh = $dbh;\n        }\n\n        public function getSourceContext(string $name): Source\n        {\n            if (false === $source = $this->getValue('source', $name)) {\n                throw new \\Twig\\Error\\LoaderError(sprintf('Template \"%s\" does not exist.', $name));\n            }\n\n            return new \\Twig\\Source($source, $name);\n        }\n\n        public function exists(string $name)\n        {\n            return $name === $this->getValue('name', $name);\n        }\n\n        public function getCacheKey(string $name): string\n        {\n            return $name;\n        }\n\n        public function isFresh(string $name, int $time): bool\n        {\n            if (false === $lastModified = $this->getValue('last_modified', $name)) {","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/doc/recipes.rst#L408-L444","documentation":"A custom Twig LoaderError thrown by a loader's getSourceContext() when the storage backend (here a database via dbh/getValue) returns no source for the requested template name. Twig loaders must throw LoaderError from getSourceContext when a template cannot be located, so the engine (or exists()) can report the missing template clearly.","triggerScenarios":"Calling $twig->render('name') or $loader->getSourceContext('name') where the lookup row for 'name' is absent in the data source (getValue returns false); a stale/cached template name referenced by an include/extends whose row was deleted.","commonSituations":"Database-backed template storage where templates were migrated or purged; typo in template name; deploying code referencing templates not yet seeded into the DB; wrong table/connection configured for the loader.","solutions":["Verify the template name exists in the storage backend for the configured connection.","Check $this->dbh connection settings and that getValue() queries the right table/column.","Call $twig->getLoader()->exists($name) (or exists()) before rendering and fall back to a default template.","Ensure templates are seeded/deployed to the backend before referencing them."],"exampleFix":"// before\nreturn $twig->render('emails/welcome.twig', $ctx);\n// after\nif ($twig->getLoader()->exists('emails/welcome.twig')) {\n    return $twig->render('emails/welcome.twig', $ctx);\n}\nreturn $twig->render('emails/default.twig', $ctx);","handlingStrategy":"try-catch","validationCode":"if (!$loader->exists($templateName)) { /* fallback or log */ }","typeGuard":null,"tryCatchPattern":"try {\n    $html = $twig->render($name, $ctx);\n} catch (\\Twig\\Error\\LoaderError $e) {\n    $logger->warning('Template missing: ' . $name);\n    $html = $twig->render('fallback.twig', $ctx);\n}","preventionTips":["Check loader->exists() for dynamic/user-supplied template names before rendering.","Seed template rows into the DB as part of deployment migrations.","Log the requested name in the loader's exists()/getSourceContext() to catch naming drift.","Keep template names centralized in constants/services to avoid typos."],"tags":["twig","loader","template-not-found","database"],"backgroundTag":"resource-not-found","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}