{"id":"fe76c88aea23f13c","repo":"pallets/flask","slug":"function-reference-must-be-a-simple-name-app-nam","errorCode":null,"errorMessage":"Function reference must be a simple name: {app_name!r}.","messagePattern":"Function reference must be a simple name: (.+?)\\.","errorType":"exception","errorClass":"NoAppException","httpStatus":null,"severity":"error","filePath":"src/flask/cli.py","lineNumber":142,"sourceCode":"    from . import Flask\n\n    # Parse app_name as a single expression to determine if it's a valid\n    # attribute name or function call.\n    try:\n        expr = ast.parse(app_name.strip(), mode=\"eval\").body\n    except SyntaxError:\n        raise NoAppException(\n            f\"Failed to parse {app_name!r} as an attribute name or function call.\"\n        ) from None\n\n    if isinstance(expr, ast.Name):\n        name = expr.id\n        args = []\n        kwargs = {}\n    elif isinstance(expr, ast.Call):\n        # Ensure the function name is an attribute name only.\n        if not isinstance(expr.func, ast.Name):\n            raise NoAppException(\n                f\"Function reference must be a simple name: {app_name!r}.\"\n            )\n\n        name = expr.func.id\n\n        # Parse the positional and keyword arguments as literals.\n        try:\n            args = [ast.literal_eval(arg) for arg in expr.args]\n            kwargs = {\n                kw.arg: ast.literal_eval(kw.value)\n                for kw in expr.keywords\n                if kw.arg is not None\n            }\n        except ValueError:\n            # literal_eval gives cryptic error messages, show a generic\n            # message with the full expression instead.\n            raise NoAppException(\n                f\"Failed to parse arguments as literal values: {app_name!r}.\"","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/pallets/flask/blob/6a2f545bfd8ed31e19066a299296917e034aca58/src/flask/cli.py#L124-L160","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Expose the factory as a module-level function and reference it by its simple name: `flask --app 'module:create_app()' run`.","Add a thin module-level wrapper: `def create_app(): return factories.create()` and point --app at that.","Put the dots on the module side of the colon: `flask --app 'pkg.submodule:create_app' run`."],"exampleFix":"# before\nflask --app 'myapp:builders.make_app()' run\n\n# after (in myapp.py)\ndef create_app():\n    return builders.make_app()\n# flask --app 'myapp:create_app' run","handlingStrategy":"validation","validationCode":"import ast\nnode = ast.parse('create_app()', mode='eval').body\nassert isinstance(node.func, ast.Name), 'factory call must be a bare name, not attribute/expression'","typeGuard":"def is_simple_factory_call(s):\n    import ast\n    try:\n        n = ast.parse(s.strip(), mode='eval').body\n        return isinstance(n, ast.Call) and isinstance(n.func, ast.Name)\n    except SyntaxError:\n        return False","tryCatchPattern":null,"preventionTips":["Call factories by simple name only: 'module:create_app()' — not 'module:pkg.factory()' or chained calls","If the factory lives on a nested object, wrap it in a top-level function in the module and reference that","Keep the module path on the left of the colon; only a bare function name (optionally with args) on the right"],"tags":["flask","cli","parsing","app-factory"],"analyzedSha":"6a2f545bfd8ed31e19066a299296917e034aca58","analyzedAt":"2026-07-31T19:13:49.921Z","schemaVersion":2}