{"id":"97fb03a4ece6b66b","repo":"pallets/flask","slug":"failed-to-parse-app-name-r-as-an-attribute-name","errorCode":null,"errorMessage":"Failed to parse {app_name!r} as an attribute name or function call.","messagePattern":"Failed to parse (.+?) as an attribute name or function call\\.","errorType":"exception","errorClass":"NoAppException","httpStatus":null,"severity":"error","filePath":"src/flask/cli.py","lineNumber":131,"sourceCode":"        return True\n    finally:\n        # Delete tb to break a circular reference.\n        # https://docs.python.org/2/library/sys.html#sys.exc_info\n        del tb\n\n\ndef find_app_by_string(module: ModuleType, app_name: str) -> Flask:\n    \"\"\"Check if the given string is a variable name or a function. Call\n    a function to get the app instance, or return the variable directly.\n    \"\"\"\n    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:","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/pallets/flask/blob/6a2f545bfd8ed31e19066a299296917e034aca58/src/flask/cli.py#L113-L149","documentation":"A `NoAppException` from `find_app_by_string`, which handles the part after the colon in `--app module:name`. Flask parses that string with `ast.parse(..., mode='eval')`; if it isn't valid Python for a single expression (SyntaxError), or parses to something other than a bare name or a function call (e.g. an attribute chain, subscript, or literal), Flask rejects it because it only supports `name` or `factory(literal_args)` forms.","triggerScenarios":"`flask --app 'module:...'` where the part after the colon is malformed or unsupported: unbalanced parens (`create_app(`), an attribute access (`pkg.app` after the colon), a subscript (`apps[0]`), stray shell-quoting artifacts, or an empty/whitespace name.","commonSituations":"Shell quoting mistakes where the shell eats quotes or parentheses before Flask sees them (especially in Windows cmd vs PowerShell vs bash); using dotted attribute paths after the colon expecting import-string semantics like gunicorn's; typos leaving invalid syntax.","solutions":["Quote the whole app string so the shell passes it intact: `flask --app 'myapp:create_app(\"dev\")' run`.","Use only a simple name or call after the colon — dots belong before the colon (`pkg.module:app`, not `pkg:module.app`).","Check for balanced parentheses and valid Python literals in the factory-call form."],"exampleFix":"# before\nflask --app myapp:create_app(dev) run   # shell mangles parens; 'dev' not a literal\n\n# after\nflask --app 'myapp:create_app(\"dev\")' run","handlingStrategy":"validation","validationCode":"import ast\napp_name = 'create_app(\"prod\")'\ntry:\n    ast.parse(app_name.strip(), mode='eval')\nexcept SyntaxError:\n    raise SystemExit('invalid --app expression')","typeGuard":"def is_valid_app_expr(s):\n    import ast\n    try:\n        node = ast.parse(s.strip(), mode='eval').body\n        return isinstance(node, (ast.Name, ast.Attribute, ast.Call))\n    except SyntaxError:\n        return False","tryCatchPattern":null,"preventionTips":["Use only the documented forms after the colon: 'name', 'name.attr', or 'factory(args)'","Quote the whole --app value in the shell so parentheses and quotes survive shell parsing","Avoid arbitrary expressions — the CLI parses a restricted subset of Python, not full eval"],"tags":["flask","cli","parsing","configuration"],"analyzedSha":"6a2f545bfd8ed31e19066a299296917e034aca58","analyzedAt":"2026-07-31T19:13:49.921Z","schemaVersion":2}