How It Works Features Pricing Blog
Log In Start Free Trial
Flask · Python

Fix ImportError: cannot import name 'app' from 'main' in Flask

This error occurs when Python cannot find the 'app' name in the 'main' module, usually due to circular imports, incorrect module paths, or the Flask app being defined with a different variable name. Fix it by restructuring imports to avoid circular dependencies or using an application factory pattern.

Reading the Stack Trace

Traceback (most recent call last): File "/app/run.py", line 1, in <module> from main import app ImportError: cannot import name 'app' from 'main' (/app/main/__init__.py) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/app/run.py", line 1, in <module> from main import app File "/app/main/__init__.py", line 3, in <module> from main.routes import bp File "/app/main/routes.py", line 1, in <module> from main import app ImportError: cannot import name 'app' from partially initialized module 'main' (most likely due to a circular import) (/app/main/__init__.py)

Here's what each line means:

Common Causes

1. Circular import between app and routes

The main module imports routes, and routes imports app from main, creating a circular dependency that prevents either from fully loading.

# main/__init__.py
from flask import Flask
app = Flask(__name__)
from main.routes import bp
app.register_blueprint(bp)

# main/routes.py
from main import app
from flask import Blueprint
bp = Blueprint('main', __name__)

@bp.route('/')
def index():
    return 'Hello'

2. Wrong module name in import

The import path references 'main' but the Flask app is defined in a file or package with a different name.

# The app is in application.py, not main.py
# run.py
from main import app  # Wrong: should be from application import app

The Fix

Use the application factory pattern to break the circular import. The create_app function defers route imports until after Flask is initialized, and routes use Blueprint instead of importing the app directly.

Before (broken)
# main/__init__.py
from flask import Flask
app = Flask(__name__)
from main.routes import bp
app.register_blueprint(bp)

# main/routes.py
from main import app
from flask import Blueprint
bp = Blueprint('main', __name__)

@bp.route('/')
def index():
    return 'Hello'
After (fixed)
# main/__init__.py
from flask import Flask

def create_app():
    app = Flask(__name__)

    from main.routes import bp
    app.register_blueprint(bp)

    return app

# main/routes.py
from flask import Blueprint

bp = Blueprint('main', __name__)

@bp.route('/')
def index():
    return 'Hello'

# run.py
from main import create_app
app = create_app()

if __name__ == '__main__':
    app.run(debug=True)

Testing the Fix

import pytest
from main import create_app


@pytest.fixture
def app():
    app = create_app()
    app.config['TESTING'] = True
    return app


@pytest.fixture
def client(app):
    return app.test_client()


def test_index_returns_200(client):
    response = client.get('/')
    assert response.status_code == 200


def test_index_returns_hello(client):
    response = client.get('/')
    assert response.data == b'Hello'


def test_app_is_created(app):
    assert app is not None
    assert app.config['TESTING'] is True

Run your tests:

pytest

Pushing Through CI/CD

git checkout -b fix/circular-import-flask,git add main/__init__.py main/routes.py run.py,git commit -m "fix: use application factory pattern to resolve circular imports",git push origin fix/circular-import-flask

Your CI config should look something like this:

name: CI
on:
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - run: pip install -r requirements.txt
      - run: pytest --tb=short
      - run: flake8 .

The Full Manual Process: 18 Steps

Here's every step you just went through to fix this one bug:

  1. Notice the error alert or see it in your monitoring tool
  2. Open the error dashboard and read the stack trace
  3. Identify the file and line number from the stack trace
  4. Open your IDE and navigate to the file
  5. Read the surrounding code to understand context
  6. Reproduce the error locally
  7. Identify the root cause
  8. Write the fix
  9. Run the test suite locally
  10. Fix any failing tests
  11. Write new tests covering the edge case
  12. Run the full test suite again
  13. Create a new git branch
  14. Commit and push your changes
  15. Open a pull request
  16. Wait for code review
  17. Merge and deploy to production
  18. Monitor production to confirm the error is resolved

Total time: 30-60 minutes. For one bug.

Or Let bugstack Fix It in Under 2 minutes

Every step above? bugstack does it automatically.

Step 1: Install the SDK

pip install bugstack

Step 2: Initialize

import bugstack

bugstack.init(api_key=os.environ["BUGSTACK_API_KEY"])

Step 3: There is no step 3.

bugstack handles everything from here:

  1. Captures the stack trace and request context
  2. Pulls the relevant source files from your GitHub repo
  3. Analyzes the error and understands the code context
  4. Generates a minimal, verified fix
  5. Runs your existing test suite
  6. Pushes through your CI/CD pipeline
  7. Deploys to production (or opens a PR for review)

Time from error to fix deployed: Under 2 minutes.

Human involvement: zero.

Try bugstack Free →

No credit card. 5-minute setup. Cancel anytime.

Deploying the Fix (Manual Path)

  1. Run pytest locally to confirm the factory pattern resolves the import error.
  2. Open a pull request with the restructured imports.
  3. Wait for CI checks to pass on the PR.
  4. Have a teammate review the application factory changes.
  5. Merge to main and verify the app starts correctly in staging.

Frequently Asked Questions

BugStack verifies the app starts without import errors, runs the full test suite, and confirms all routes are registered and responding correctly.

All fixes are submitted as pull requests. Your CI pipeline validates the app starts and passes tests before you review and merge.

It's a Flask pattern where you define a create_app() function that builds and configures the app. This avoids circular imports and makes testing easier by allowing multiple app instances.

You can, but you must be careful with import ordering. The factory pattern is recommended by the Flask documentation as the standard approach for non-trivial applications.