{"record":{"id":"c7b8e9b734375f93","repo":"pallets/flask","slug":"a-valid-flask-application-was-not-obtained-from","errorCode":null,"errorMessage":"A valid Flask application was not obtained from '{module.__name__}:{app_name}'.","messagePattern":"A valid Flask application was not obtained from '(.+?):(.+?)'\\.","errorType":"exception","errorClass":"NoAppException","httpStatus":null,"severity":"error","filePath":"src/flask/cli.py","lineNumber":194,"sourceCode":"    if inspect.isfunction(attr):\n        try:\n            app = attr(*args, **kwargs)\n        except TypeError as e:\n            if not _called_with_wrong_args(attr):\n                raise\n\n            raise NoAppException(\n                f\"The factory {app_name!r} in module\"\n                f\" {module.__name__!r} could not be called with the\"\n                \" specified arguments.\"\n            ) from e\n    else:\n        app = attr\n\n    if isinstance(app, Flask):\n        return app\n\n    raise NoAppException(\n        \"A valid Flask application was not obtained from\"\n        f\" '{module.__name__}:{app_name}'.\"\n    )\n\n\ndef prepare_import(path: str) -> str:\n    \"\"\"Given a filename this will try to calculate the python path, add it\n    to the search path and return the actual module name that is expected.\n    \"\"\"\n    path = os.path.realpath(path)\n\n    fname, ext = os.path.splitext(path)\n    if ext == \".py\":\n        path = fname\n\n    if os.path.basename(path) == \"__init__\":\n        path = os.path.dirname(path)\n","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/pallets/flask/blob/3596b1ab61cea85edb8970e83ff61daa073facf8/src/flask/cli.py#L176-L212","documentation":"After resolving the attribute named in the --app/FLASK_APP string (either a plain attribute or the return value of a called factory), Flask checks isinstance(app, Flask). If the resolved object is not a Flask instance, it raises NoAppException stating no valid app was obtained from 'module:attribute'. The attribute was found and (if a function) called successfully, but it did not yield a Flask application object.","triggerScenarios":"Pointing --app at a module:attribute where the attribute is a dict, a string, a non-Flask WSGI callable, or a function whose return value is not a Flask instance. For example the attribute holds a configuration dict, or a factory returns a plain dict/None instead of app.","commonSituations":"Naming the wrong attribute in FLASK_APP (e.g. 'mypkg:config' instead of 'mypkg:app'). A factory function that returns the wrong object after a refactor. Returning a blueprint or an app group instead of a single Flask app.","solutions":["Verify the named attribute is actually a Flask instance or a factory returning one: print(type(mymodule.app)).","Point --app at the correct attribute name that holds the Flask app.","If using a factory, ensure it returns app (return app) rather than a dict, None, or other object."],"exampleFix":"# before\nexport FLASK_APP='mypkg:db_config'   # db_config is a dict\n\n# after\nexport FLASK_APP='mypkg:app'         # app is a Flask instance","handlingStrategy":"type-guard","validationCode":"from flask import Flask\n\ndef assert_flask_app(attr_path, obj):\n    if not isinstance(obj, Flask):\n        raise TypeError(f'{attr_path} resolved to {type(obj).__name__}, not a Flask app')\n    return obj","typeGuard":"from flask import Flask\nimport typing as t\n\ndef is_flask_app(obj: t.Any) -> 't.TypeGuard[Flask]':\n    return isinstance(obj, Flask)","tryCatchPattern":"from flask.cli import NoAppException\ntry:\n    app = locate_app(module, name)\nexcept NoAppException as e:\n    if 'not obtained' in str(e):\n        print(f'{module}:{name} is not a Flask instance; check the attribute name')\n    raise","preventionTips":["Name the Flask instance consistently (e.g. always 'app') across modules.","Add an assertion at import time that the exported symbol is a Flask instance."],"tags":["flask","cli","app-resolution","configuration"],"backgroundTag":null,"analyzedSha":"3596b1ab61cea85edb8970e83ff61daa073facf8","analyzedAt":"2026-08-11T20:11:52.622Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}