{"record":{"id":"2ab0c46128f12e17","repo":"Textualize/textual","slug":"multiple-apps-found-lib-r-try-specifying-app-wi","errorCode":null,"errorMessage":"Multiple apps found {lib!r}, try specifying app with \"foo.py:app\"","messagePattern":"Multiple apps found (.+?), try specifying app with \"foo\\.py:app\"","errorType":"exception","errorClass":"AppFail","httpStatus":null,"severity":"error","filePath":"src/textual/_import_app.py","lineNumber":101,"sourceCode":"                except KeyError:\n                    raise AppFail(f\"App {name!r} not found in {lib!r}\")\n            else:\n                # Find an App class or instance that is *not* the base class\n                apps = [\n                    value\n                    for value in global_vars.values()\n                    if (\n                        isinstance(value, App)\n                        or (inspect.isclass(value) and issubclass(value, App))\n                        and value is not App\n                    )\n                ]\n                if not apps:\n                    raise AppFail(\n                        f'Unable to find app in {lib!r}, try specifying app with \"foo.py:app\"'\n                    )\n                if len(apps) > 1:\n                    raise AppFail(\n                        f'Multiple apps found {lib!r}, try specifying app with \"foo.py:app\"'\n                    )\n                app = apps[0]\n        app._BASE_PATH = path\n\n    else:\n        # Assuming the user wants to import the file\n        sys.path.append(\"\")\n        try:\n            module = importlib.import_module(lib)\n        except ImportError as error:\n            raise AppFail(str(error))\n\n        find_app = name or \"app\"\n        try:\n            app = getattr(module, find_app or \"app\")\n        except AttributeError:\n            raise AppFail(f\"Unable to find {find_app!r} in {module!r}\")","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/_import_app.py#L83-L119","documentation":"When no explicit app name is given, Textual's import_app() collects every global in the file that is an App instance or App subclass; if more than one is found it cannot choose between them, so it refuses to guess and asks you to disambiguate with the `file:app` syntax. Note the message text says 'Multiple apps found' followed by the path. This commonly fires when a file defines several demo apps or imports App subclasses for use as screens.","triggerScenarios":"Running `textual run foo.py` on a file that defines two or more App subclasses/instances at module level; a file that imports other app classes (e.g. `from other import OtherApp`) alongside its own app; a gallery/demo file containing many small apps.","commonSituations":"Demo or example files with multiple sample apps; refactoring that leaves an old app class alongside the new one; importing an app class for isinstance checks or reuse, which inadvertently registers it as a candidate global.","solutions":["Name the app explicitly: `textual run foo.py:MyApp`","Delete or rename unused App classes so only one remains at module level","Import other app classes inside functions rather than at module top level"],"exampleFix":"# before\n# foo.py\nclass LeftApp(App): ...\nclass RightApp(App): ...\n# CLI: textual run foo.py  -> AppFail: Multiple apps found\n\n# after\n# CLI: textual run foo.py:LeftApp","handlingStrategy":"validation","validationCode":"apps = discover_apps(\"foo.py\")  # see errorIndex 12 helper\nif len(apps) > 1:\n    raise SystemExit(\"Multiple apps; specify foo.py:AppName\")","typeGuard":null,"tryCatchPattern":"try:\n    app = import_app(\"foo.py\")\nexcept AppFail:\n    app = import_app(\"foo.py:MyApp\")  # disambiguate explicitly","preventionTips":["Keep one App class per demo file","Import foreign app classes lazily inside functions","Always pass the explicit name in automation scripts"],"tags":["textual","import","app-discovery","ambiguity"],"backgroundTag":"ambiguous-entrypoint","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}