{"record":{"id":"6a6ac33c7b4c4811","repo":"nodejs/node","slug":"async-mode-requires-a-body-stream-to-be-passed-to","errorCode":null,"errorMessage":"Async mode requires a body stream to be passed to a template module.  Use the async methods of the API you are using.","messagePattern":"Async mode requires a body stream to be passed to a template module\\.  Use the async methods of the API you are using\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"tools/inspector_protocol/jinja2/environment.py","lineNumber":1148,"sourceCode":"    def __repr__(self):\n        if self.name is None:\n            name = 'memory:%x' % id(self)\n        else:\n            name = repr(self.name)\n        return '<%s %s>' % (self.__class__.__name__, name)\n\n\n@implements_to_string\nclass TemplateModule(object):\n    \"\"\"Represents an imported template.  All the exported names of the\n    template are available as attributes on this object.  Additionally\n    converting it into an unicode- or bytestrings renders the contents.\n    \"\"\"\n\n    def __init__(self, template, context, body_stream=None):\n        if body_stream is None:\n            if context.environment.is_async:\n                raise RuntimeError('Async mode requires a body stream '\n                                   'to be passed to a template module.  Use '\n                                   'the async methods of the API you are '\n                                   'using.')\n            body_stream = list(template.root_render_func(context))\n        self._body_stream = body_stream\n        self.__dict__.update(context.get_exported())\n        self.__name__ = template.name\n\n    def __html__(self):\n        return Markup(concat(self._body_stream))\n\n    def __str__(self):\n        return concat(self._body_stream)\n\n    def __repr__(self):\n        if self.__name__ is None:\n            name = 'memory:%x' % id(self)\n        else:","sourceCodeStart":1130,"sourceCodeEnd":1166,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/inspector_protocol/jinja2/environment.py#L1130-L1166","documentation":"TemplateModule wraps an imported template (created via {% import %} or Environment.get_template().module). Its constructor must materialize the rendered output: normally it does list(template.root_render_func(context)), but in an async environment root_render_func is an async generator that cannot be drained synchronously. Therefore Jinja2 refuses to construct the module without a pre-collected body_stream.","triggerScenarios":"Constructing a TemplateModule synchronously (or calling .module on a template) while Environment(enable_async=True) is set and no body_stream was pre-collected via the async render path. Typically hit when mixing {% import 'macros.html' as m %} with an async environment, or calling template.module instead of await template.make_module_async().","commonSituations":"Adopting async rendering under asyncio/Starlette/Sanic/aiohttp and reusing existing {% import %} macros; upgrading a sync Jinja2 codebase to enable_async=True without converting the import/module access sites.","solutions":["Render via the async API so Jinja2 collects the body stream for you: use await template.render_async() / async for chunk in template.generate_async(), and access the imported module through await template.make_module_async() (or context_vars) instead of the synchronous .module property.","If you only need macros, inline them or pass rendered strings rather than importing a module under enable_async.","If async is not actually required, construct the Environment without enable_async (the default) so the synchronous module path works.","Bump/verify your Jinja2 version supports the async module API (make_module_async / generate_async); older vendored copies may lack it."],"exampleFix":"// before\nenv = Environment(loader=..., enable_async=True)\ntmpl = env.get_template('page.html')\nmod = tmpl.module  # raises: async mode requires a body stream\n\n// after\nenv = Environment(loader=..., enable_async=True)\ntmpl = env.get_template('page.html')\nmod = await tmpl.make_module_async()  # body stream collected asynchronously","handlingStrategy":"validation","validationCode":"from jinja2 import Environment\n\ndef safe_module(env, name):\n    tmpl = env.get_template(name)\n    if env.is_async:\n        raise RuntimeError(\n            'cannot access .module synchronously under enable_async; '\n            'await tmpl.make_module_async() instead')\n    return tmpl.module","typeGuard":"def supports_sync_module(env: Environment) -> bool:\n    return not getattr(env, 'is_async', False)","tryCatchPattern":"try:\n    mod = tmpl.module\nexcept RuntimeError as e:\n    if 'Async mode' in str(e):\n        raise RuntimeError('await tmpl.make_module_async() under enable_async') from e\n    raise","preventionTips":["Decide upfront whether your Environment is async; never mix .module access with enable_async=True.","Centralize template import/module access in one helper that branches on env.is_async.","When enabling enable_async, audit every {% import %} and .module usage site."],"tags":["jinja2","async","templating","import"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}