pallets/flask · error · RuntimeError

Working outside of application context. Attempted to use fu

Error message

Working outside of application context.

Attempted to use functionality that expected a current application to be set. To
solve this, set up an app context using 'with app.app_context()'. See the
documentation on app context for more information.

What it means

Flask exposes `current_app`, `g`, and `app_ctx` as werkzeug LocalProxy objects bound to the `flask.app_ctx` ContextVar (src/flask/globals.py:40-48). When no AppContext has been pushed onto that ContextVar, dereferencing the proxy raises this RuntimeError with the configured `unbound_message`. It exists because these globals are context-local: Flask cannot know which application you mean unless an app context is active on the current thread/task.

Source

Thrown at src/flask/globals.py:33

    T = t.TypeVar("T", covariant=True)

    class ProxyMixin(t.Protocol[T]):
        def _get_current_object(self) -> T: ...

    # These subclasses inform type checkers that the proxy objects look like the
    # proxied type along with the _get_current_object method.
    class FlaskProxy(ProxyMixin[Flask], Flask): ...

    class AppContextProxy(ProxyMixin[AppContext], AppContext): ...

    class _AppCtxGlobalsProxy(ProxyMixin[_AppCtxGlobals], _AppCtxGlobals): ...

    class RequestProxy(ProxyMixin[Request], Request): ...

    class SessionMixinProxy(ProxyMixin[SessionMixin], SessionMixin): ...


_no_app_msg = """\
Working outside of application context.

Attempted to use functionality that expected a current application to be set. To
solve this, set up an app context using 'with app.app_context()'. See the
documentation on app context for more information.\
"""
_cv_app: ContextVar[AppContext] = ContextVar("flask.app_ctx")
app_ctx: AppContextProxy = LocalProxy(  # type: ignore[assignment]
    _cv_app, unbound_message=_no_app_msg
)
current_app: FlaskProxy = LocalProxy(  # type: ignore[assignment]
    _cv_app, "app", unbound_message=_no_app_msg
)
g: _AppCtxGlobalsProxy = LocalProxy(  # type: ignore[assignment]
    _cv_app, "g", unbound_message=_no_app_msg
)

_no_req_msg = """\

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Wrap the failing code in an explicit app context: `with app.app_context(): ...`
  2. In app-factory projects, import/call `create_app()` in your script or worker and push its context before using extensions.
  3. For background threads, pass the real app object (`current_app._get_current_object()`) into the thread and push a context there.
  4. In tests, use a fixture that pushes an app context (e.g. pytest fixture yielding inside `with app.app_context()`).
  5. For Celery, configure a task base class that pushes an app context around each task run.

Example fix

# before
from myapp import db

def seed():
    db.session.add(User(name="a"))
    db.session.commit()

# after
from myapp import create_app, db

def seed():
    app = create_app()
    with app.app_context():
        db.session.add(User(name="a"))
        db.session.commit()
Defensive patterns

Strategy: validation

Validate before calling

from flask import current_app
from flask.globals import app_ctx

if app_ctx:  # an app context is active
    db_uri = current_app.config["SQLALCHEMY_DATABASE_URI"]
else:
    with app.app_context():
        db_uri = app.config["SQLALCHEMY_DATABASE_URI"]

Type guard

from flask import has_app_context

def in_app_context() -> bool:
    """True if current_app / g are safe to touch."""
    return has_app_context()

Try / catch

try:
    value = current_app.config["MY_KEY"]
except RuntimeError as exc:
    if "application context" in str(exc):
        with app.app_context():
            value = app.config["MY_KEY"]
    else:
        raise

Prevention

When it happens

Trigger: Accessing `current_app`, `g`, or anything that reads them (e.g. `current_app.config`, extensions like SQLAlchemy's `db.session`, `url_for` without a request) from code running outside `with app.app_context()`: module import time, CLI scripts, background threads, Celery tasks, or APScheduler jobs. Also raised when a thread spawned from a view accesses `current_app`, since ContextVars do not propagate to new threads.

Common situations: Running one-off database or seed scripts that import models using `current_app`; Celery/RQ workers whose tasks touch Flask extensions without pushing an app context; accessing `current_app` at module top-level in an app-factory project; unit tests calling code directly without a `with app.app_context()` fixture; background threads started with `threading.Thread` from inside a request.

Related errors


AI-assisted analysis of pallets/flask@6a2f545bfd (2026-07-31). Data as JSON: /data/errors/c05c367d66614a5c.json. Report an issue: GitHub ↗.