pallets/flask · error · NoAppException

Function reference must be a simple name: {app_name!r}.

Error message

Function reference must be a simple name: {app_name!r}.

What it means

A `NoAppException` from `find_app_by_string` when the post-colon expression parses as a call whose function part is not a plain `ast.Name` — e.g. `factory.method(...)`, `obj[0](...)`, or `(lambda: x)()`. Flask deliberately restricts the callable to a simple module-level attribute name so it can look it up with `getattr(module, name)`; arbitrary expressions are not evaluated for safety and simplicity.

Source

Thrown at src/flask/cli.py:142

    from . import Flask

    # Parse app_name as a single expression to determine if it's a valid
    # attribute name or function call.
    try:
        expr = ast.parse(app_name.strip(), mode="eval").body
    except SyntaxError:
        raise NoAppException(
            f"Failed to parse {app_name!r} as an attribute name or function call."
        ) from None

    if isinstance(expr, ast.Name):
        name = expr.id
        args = []
        kwargs = {}
    elif isinstance(expr, ast.Call):
        # Ensure the function name is an attribute name only.
        if not isinstance(expr.func, ast.Name):
            raise NoAppException(
                f"Function reference must be a simple name: {app_name!r}."
            )

        name = expr.func.id

        # Parse the positional and keyword arguments as literals.
        try:
            args = [ast.literal_eval(arg) for arg in expr.args]
            kwargs = {
                kw.arg: ast.literal_eval(kw.value)
                for kw in expr.keywords
                if kw.arg is not None
            }
        except ValueError:
            # literal_eval gives cryptic error messages, show a generic
            # message with the full expression instead.
            raise NoAppException(
                f"Failed to parse arguments as literal values: {app_name!r}."

View on GitHub ↗ (pinned to 6a2f545bfd)

Solutions

  1. Expose the factory as a module-level function and reference it by its simple name: `flask --app 'module:create_app()' run`.
  2. Add a thin module-level wrapper: `def create_app(): return factories.create()` and point --app at that.
  3. Put the dots on the module side of the colon: `flask --app 'pkg.submodule:create_app' run`.

Example fix

# before
flask --app 'myapp:builders.make_app()' run

# after (in myapp.py)
def create_app():
    return builders.make_app()
# flask --app 'myapp:create_app' run
Defensive patterns

Strategy: validation

Validate before calling

import ast
node = ast.parse('create_app()', mode='eval').body
assert isinstance(node.func, ast.Name), 'factory call must be a bare name, not attribute/expression'

Type guard

def is_simple_factory_call(s):
    import ast
    try:
        n = ast.parse(s.strip(), mode='eval').body
        return isinstance(n, ast.Call) and isinstance(n.func, ast.Name)
    except SyntaxError:
        return False

Prevention

When it happens

Trigger: `flask --app 'module:factories.create(...)' run`, `--app 'module:AppBuilder().build()'`, or any call target that is an attribute chain, subscript, or nested call rather than a bare function name defined at module level.

Common situations: Trying to call a factory that lives on a class or in a nested namespace object; porting gunicorn-style entrypoints where dotted call targets are common; wrapping the factory in a container object instead of exposing it at module top level.

Related errors


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