I just encountered this problem. The solution is to override `app.jinja_env.loader` with `ModuleLoader` instead of `app.jinja_loader`.
The problem apparently arises when your `ModuleLoader` (or `ChoiceLoader`, or what have you) is being dispatched by `DispatchingJinjaLoader`, which assumes `get_source`, instead of operating on its own. Note that `DispatchingJinjaLoader` is only useful for integrating the base loader with all the blueprint loaders; if you already pre-compiled everything available to the `DispatchingJinjaLoader`, there's no point in dispatching anymore.
Basically, you can structure your application like this:
```py
import flask
import jinja2
import blueprints.foo
import blueprints.bar
app = flask.Flask(__name__)
# Make sure to register the blueprints before template compilation.
app.register_blueprint(blueprints.foo.foo)
app.register_blueprint(blueprints.bar.bar)
# Register filters and context processors before compilation, too.
@app.template_filter('foo')
def filter_foo(val):
return val
@app.context_processor
def injector():
return dict()
app.jinja_env.compile_templates('/path/to/compiled/templates') # Of course this may be done separately.
app.jinja_env.loader = jinja2.ModuleLoader('/path/to/compiled/templates')
```