{"record":{"id":"79ec98cba85cf445","repo":"nodejs/node","slug":"s-cannot-provide-access-to-the-source","errorCode":null,"errorMessage":"%s cannot provide access to the source","messagePattern":"(.+?) cannot provide access to the source","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"tools/inspector_protocol/jinja2/loaders.py","lineNumber":89,"sourceCode":"        \"\"\"Get the template source, filename and reload helper for a template.\n        It's passed the environment and template name and has to return a\n        tuple in the form ``(source, filename, uptodate)`` or raise a\n        `TemplateNotFound` error if it can't locate the template.\n\n        The source part of the returned tuple must be the source of the\n        template as unicode string or a ASCII bytestring.  The filename should\n        be the name of the file on the filesystem if it was loaded from there,\n        otherwise `None`.  The filename is used by python for the tracebacks\n        if no loader extension is used.\n\n        The last item in the tuple is the `uptodate` function.  If auto\n        reloading is enabled it's always called to check if the template\n        changed.  No arguments are passed so the function must store the\n        old state somewhere (for example in a closure).  If it returns `False`\n        the template will be reloaded.\n        \"\"\"\n        if not self.has_source_access:\n            raise RuntimeError('%s cannot provide access to the source' %\n                               self.__class__.__name__)\n        raise TemplateNotFound(template)\n\n    def list_templates(self):\n        \"\"\"Iterates over all templates.  If the loader does not support that\n        it should raise a :exc:`TypeError` which is the default behavior.\n        \"\"\"\n        raise TypeError('this loader cannot iterate over all templates')\n\n    @internalcode\n    def load(self, environment, name, globals=None):\n        \"\"\"Loads a template.  This method looks up the template in the cache\n        or loads one by calling :meth:`get_source`.  Subclasses should not\n        override this method as loaders working on collections of other\n        loaders (such as :class:`PrefixLoader` or :class:`ChoiceLoader`)\n        will not call this method but `get_source` directly.\n        \"\"\"\n        code = None","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/inspector_protocol/jinja2/loaders.py#L71-L107","documentation":"BaseLoader.get_source checks the class attribute has_source_access; when it is False the loader cannot expose raw template source and get_source raises RuntimeError naming the loader class. In this codebase ModuleLoader sets has_source_access = False (loaders.py:434) because it serves precompiled bytecode modules, not source.","triggerScenarios":"Calling loader.get_source(env, name) on a ModuleLoader (or any loader with has_source_access = False), or any code path that expects source — debugging tools, reload checks, or compile_templates introspection — against such a loader.","commonSituations":"Shipping precompiled templates via ModuleLoader for performance/distribution, then running tooling (debuggers, source-inspection, auto-reload) that assumes source is available.","solutions":["Do not call get_source on loaders where has_source_access is False; use load() to obtain a compiled Template instead.","Provide a source-capable loader (e.g. FileSystemLoader) alongside ModuleLoader via ChoiceLoader if source access is required.","Check loader.has_source_access before invoking get_source."],"exampleFix":"# before\nloader = ModuleLoader('/compiled')\nsrc, fn, uptodate = loader.get_source(env, name)  # RuntimeError\n\n# after\nloader = ChoiceLoader([\n    ModuleLoader('/compiled'),\n    FileSystemLoader('/src'),\n])\ntmpl = env.get_template(name)  # uses load(), not get_source()","handlingStrategy":"type-guard","validationCode":"def assert_source_access(loader):\n    if not getattr(loader, 'has_source_access', False):\n        raise TypeError('loader %s cannot provide source; use load() instead' % type(loader).__name__)","typeGuard":"def loader_has_source(loader) -> bool:\n    return bool(getattr(loader, 'has_source_access', False))","tryCatchPattern":"try:\n    source, fn, uptodate = loader.get_source(env, name)\nexcept RuntimeError as e:\n    if 'cannot provide access' in str(e):\n        tmpl = env.get_template(name)  # fall back to load()\n    else:\n        raise","preventionTips":["Check loader.has_source_access before calling get_source.","Pair ModuleLoader with a source-capable loader via ChoiceLoader when source access is needed.","Treat ModuleLoader as bytecode-only; never assume source is available."],"tags":["jinja2","loader","module-loader","runtime-error"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}