# Behavior traces — pallets/flask

> Canonical page: https://codevetter.com/unpack/flask/behavior-traces

# Behavior traces — pallets/flask

Scanned commit d73fa1cdcbd8b1465c151db8924ba58b1dd14e35 (2026-09-08). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Three flows dominate: application construction, WSGI request dispatch, and CLI invocation. Construction is `Flask.__init__` → `App.__init__` → `Scaffold.__init__`, ending with an auto-registered static route that holds only a weakref to the app. Request dispatch is `__call__` → `wsgi_app` → `AppContext.push` (session open, then routing) → `full_dispatch_request` → `preprocess_request` → `dispatch_request` → `finalize_request` → `process_response` (session save) → `ctx.pop` (teardowns). CLI invocation is `main` → `FlaskGroup.make_context` (sets `FLASK_RUN_FROM_CLI`) → eager `--env-file`/`--app` callbacks → `ScriptInfo.load_app` → command body with an app context pushed via `ctx.with_resource`.
- Startup: `Flask.__init__` calls `super().__init__` (App → Scaffold), creates `self.cli = cli.AppGroup()` named after the app, then — if `has_static_folder` — asserts `bool(static_host) == host_matching` and registers `f"{static_url_path}/<path:filename>"` with a `weakref.ref(self)` closure to avoid an app↔view reference cycle (issue #3761). — [src/flask/app.py#L311-L365](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L311-L365)
- Startup: `App.__init__` resolves `instance_path` (rejecting relative paths), builds `config` via `make_config`, instantiates `aborter`, `json_provider_class(self)`, the empty `blueprints`/`extensions` dicts, `url_map_class(host_matching=...)`, and sets `_got_first_request = False`. — [src/flask/sansio/app.py#L279-L409](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/sansio/app.py#L279-L409)
- Request: `Flask.__call__` → `wsgi_app(environ, start_response)` creates the context with `self.request_context(environ)`, pushes it, dispatches, and in `finally` restores it for the debugger via `environ["werkzeug.debug.preserve_context"]` before `ctx.pop(error)`. — [src/flask/app.py#L1569-L1626](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L1569-L1626)
- Request: `AppContext.push` increments `_push_count`, returns early if already pushed, sets `_cv_app`, sends `appcontext_pushed`, then opens the session via `_get_session()` *before* calling `match_request()` — ordering that lets custom URL converters read the session. — [src/flask/ctx.py#L416-L444](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/ctx.py#L416-L444)
- Request: `full_dispatch_request` sets `_got_first_request = True` (freezing setup methods), sends `request_started`, runs `preprocess_request`, short-circuits to `finalize_request` if a `before_request` returned non-None, otherwise calls `dispatch_request`, catching exceptions into `handle_user_exception`. — [src/flask/app.py#L995-L1022](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L995-L1022) [src/flask/sansio/app.py#L410-L420](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/sansio/app.py#L410-L420)
- Request: `preprocess_request` runs `url_value_preprocessors` for `(None, *reversed(req.blueprints))` first, then `before_request_funcs` in the same order — app-level before blueprint-level, outermost blueprint first. — [src/flask/app.py#L1369-L1395](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L1369-L1395)
- Request: `dispatch_request` raises any stored `routing_exception` through `raise_routing_exception`, returns `make_default_options_response` for automatic OPTIONS, and otherwise calls `ensure_sync(self.view_functions[rule.endpoint])(**view_args)`. — [src/flask/app.py#L969-L993](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L969-L993)
- Request: `process_response` runs `ctx._after_request_functions` (from `after_this_request`) first, then app+blueprint `after_request_funcs` in reverse registration order over `chain(request.blueprints, (None,))`, then saves the session. — [src/flask/app.py#L1397-L1421](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L1397-L1421) [src/flask/ctx.py#L118-L148](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/ctx.py#L118-L148)
- Teardown: `AppContext.pop` decrements `_push_count`, returns while still nested, then under `_CollectErrors` runs `do_teardown_request`, `request.close()`, `do_teardown_appcontext`, resets the ContextVar, sends `appcontext_popped`, and finally re-raises collected errors as a `BaseExceptionGroup` on Python 3.11+. — [src/flask/ctx.py#L446-L504](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/ctx.py#L446-L504) [src/flask/helpers.py#L654-L682](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/helpers.py#L654-L682)
- Error path: `handle_exception` sends `got_request_exception`, re-raises when `PROPAGATE_EXCEPTIONS` (defaulting to `testing or debug`) is truthy, otherwise logs, wraps in `InternalServerError(original_exception=e)`, looks up a 500 handler, and finalizes with `from_error_handler=True` so response-processing failures are logged rather than raised. — [src/flask/app.py#L900-L967](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L900-L967) [src/flask/app.py#L1024-L1054](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L1024-L1054)
- Error handler lookup in `_find_error_handler` tries (specific code, then None) × (each blueprint name, then None), walking `exc_class.__mro__` at each step — so a blueprint handler for a specific code beats an app handler for that code, which beats class-based handlers. — [src/flask/sansio/app.py#L868-L891](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/sansio/app.py#L868-L891)
- CLI: `FlaskGroup.make_context` sets `os.environ["FLASK_RUN_FROM_CLI"] = "true"` so a stray module-level `app.run()` becomes a no-op that prints a red warning instead of blocking the command. — [src/flask/cli.py#L657-L676](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/cli.py#L657-L676) [src/flask/app.py#L696-L707](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/app.py#L696-L707)
- CLI: `FlaskGroup.get_command` loads `flask.commands` entry points, prefers built-ins, then calls `ScriptInfo.load_app()` and pushes an app context with `ctx.with_resource(app.app_context())` before delegating to `app.cli.get_command` — which is why `@with_appcontext` is unnecessary for app-registered commands. — [src/flask/cli.py#L600-L635](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/cli.py#L600-L635) [src/flask/cli.py#L380-L403](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/cli.py#L380-L403)
- CLI: `ScriptInfo.load_app` splits the import path on `r":(?![\\/])"` (so Windows drive letters survive), calls `prepare_import` to insert the package root into `sys.path[0]`, then `locate_app`, and finally sets `app.debug = get_debug_flag()` when `set_debug_flag` is on. — [src/flask/cli.py#L333-L370](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/cli.py#L333-L370) [src/flask/cli.py#L200-L228](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/cli.py#L200-L228)
- Streaming: `stream_with_context` builds a generator, advances it once with `next()` to capture and push the current `AppContext` (which bumps `_push_count`), yields the user's chunks inside `with ctx:`, and closes a wrapped WSGI iterator in `finally`. — [src/flask/helpers.py#L115-L150](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/helpers.py#L115-L150) [src/flask/ctx.py#L416-L432](https://github.com/pallets/flask/blob/d73fa1cdcbd8b1465c151db8924ba58b1dd14e35/src/flask/ctx.py#L416-L432)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
