Claude
Skills
Sign in
Back

debug:flask

Included with Lifetime
$97 forever

Debug Flask applications systematically with this comprehensive troubleshooting skill. Covers routing errors (404/405), Jinja2 template issues, application context problems, SQLAlchemy session management, blueprint registration failures, and circular import resolution. Provides structured four-phase debugging methodology with Flask-specific tools including Werkzeug debugger, Flask-DebugToolbar, and Flask shell for interactive investigation.

Code Review

What this skill does


# Flask Debugging Guide

A systematic approach to debugging Flask applications using established patterns and Flask-specific tooling.

## Common Error Patterns

### HTTP Status Code Errors

**404 Not Found - Routing Issues**
- Route decorator not matching requested URL
- Typos in route definitions or endpoint names
- Blueprint not registered with application
- Missing trailing slash mismatch (`strict_slashes` setting)
- URL rules registered after first request

**500 Internal Server Error**
- Unhandled exceptions in view functions
- Template rendering errors
- Database connection failures
- Malformed JSON request data (missing `Content-Type: application/json`)
- Circular imports preventing app initialization

**405 Method Not Allowed**
- HTTP method not specified in `@app.route()` methods parameter
- Form submission using wrong method (GET vs POST)

### Jinja2 Template Errors

**TemplateNotFound**
- Template not in `templates/` directory
- Custom template folder not configured
- Blueprint template folder misconfigured

**UndefinedError**
- Variable not passed to `render_template()`
- Typo in template variable name
- Accessing attribute on None object

**TemplateSyntaxError**
- Unclosed blocks (`{% if %}` without `{% endif %}`)
- Invalid filter usage
- Incorrect macro definitions

### Application Context Errors

**RuntimeError: Working outside of application context**
- Accessing `current_app` outside request/CLI context
- Database operations outside `with app.app_context():`
- Celery tasks not properly configured with app context

**RuntimeError: Working outside of request context**
- Accessing `request`, `session`, or `g` outside view function
- Background thread without request context

### SQLAlchemy Session Issues

**DetachedInstanceError**
- Accessing lazy-loaded relationship outside session
- Object expired after transaction commit
- Session closed prematurely

**InvalidRequestError: Object already attached to session**
- Adding object already in different session
- Improper session management in tests

**OperationalError: Connection pool exhausted**
- Connections not being returned to pool
- Missing `db.session.close()` or `db.session.remove()`
- Long-running transactions

### Blueprint Registration Problems

**Blueprint registration failures**
- Circular imports between blueprints
- Duplicate blueprint names
- Blueprint registered after first request
- URL prefix conflicts

### Import and Module Errors

**ImportError: cannot import name 'Flask'**
- Circular dependency in modules
- File named `flask.py` shadowing the package
- Virtual environment not activated

**ModuleNotFoundError: No module named 'flask'**
- Virtual environment not activated
- Flask not installed in current environment
- Wrong Python interpreter

## Debugging Tools

### Built-in Flask Debugger (Werkzeug)

```python
# Enable debug mode (DEVELOPMENT ONLY - NEVER IN PRODUCTION)
# Method 1: Environment variable
# export FLASK_DEBUG=1

# Method 2: In code (not recommended)
app.run(debug=True)

# Method 3: Flask CLI
# flask run --debug
```

The Werkzeug debugger provides:
- Interactive traceback with code context
- In-browser Python REPL at each stack frame
- Variable inspection at each level
- PIN-protected access (check terminal for PIN)

**Security Warning**: Never enable debug mode in production. The debugger allows arbitrary code execution from the browser.

### Python Debugger (pdb/breakpoint)

```python
# Insert breakpoint in code
def my_view():
    data = get_data()
    breakpoint()  # Python 3.7+ (or: import pdb; pdb.set_trace())
    return process(data)

# Common pdb commands:
# n (next) - Execute next line
# s (step) - Step into function
# c (continue) - Continue to next breakpoint
# p variable - Print variable value
# pp variable - Pretty print variable
# l (list) - Show current code context
# w (where) - Show stack trace
# q (quit) - Quit debugger
```

### Flask Shell

```bash
# Start interactive shell with app context
flask shell

# In shell:
>>> from app.models import User
>>> User.query.all()
>>> app.config['DEBUG']
>>> app.url_map  # View all registered routes
```

### Logging Module

```python
import logging
from flask import Flask

app = Flask(__name__)

# Configure logging
logging.basicConfig(level=logging.DEBUG)
app.logger.setLevel(logging.DEBUG)

# Add file handler for persistent logs
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.WARNING)
file_handler.setFormatter(logging.Formatter(
    '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
))
app.logger.addHandler(file_handler)

# Usage in views
@app.route('/api/data')
def get_data():
    app.logger.debug('Processing request for /api/data')
    try:
        result = fetch_data()
        app.logger.info(f'Successfully fetched {len(result)} records')
        return jsonify(result)
    except Exception as e:
        app.logger.error(f'Error fetching data: {e}', exc_info=True)
        raise
```

### Flask-DebugToolbar

```python
# Install: pip install flask-debugtoolbar

from flask import Flask
from flask_debugtoolbar import DebugToolbarExtension

app = Flask(__name__)
app.config['SECRET_KEY'] = 'dev-secret-key'
app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False

toolbar = DebugToolbarExtension(app)
```

Provides sidebar panels for:
- Request/response headers
- Template rendering details
- SQLAlchemy queries (with query time)
- Route matching information
- Configuration values
- Logging messages

### SQLAlchemy Query Logging

```python
# Enable SQL query logging
import logging
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

# Or in Flask config
app.config['SQLALCHEMY_ECHO'] = True

# For query analysis with flask-debugtoolbar
app.config['DEBUG_TB_PANELS'] = [
    'flask_debugtoolbar.panels.sqlalchemy.SQLAlchemyDebugPanel',
]
```

## The Four Phases of Flask Debugging

### Phase 1: Reproduce and Isolate

**Capture the exact error state:**

```bash
# Check Flask is running with debug enabled
flask run --debug

# View registered routes
flask routes

# Check configuration
flask shell
>>> app.config
```

**Minimal reproduction:**

```python
# Create minimal test case
def test_failing_route(client):
    response = client.get('/api/broken-endpoint')
    print(f"Status: {response.status_code}")
    print(f"Data: {response.get_data(as_text=True)}")
    assert response.status_code == 200
```

**Questions to answer:**
- Does error occur on every request or intermittently?
- What is the exact HTTP status code?
- What does the traceback show?
- What was the request payload?
- What environment variables are set?

### Phase 2: Gather Information

**Collect comprehensive context:**

```python
# Add request logging middleware
@app.before_request
def log_request_info():
    app.logger.debug('Headers: %s', dict(request.headers))
    app.logger.debug('Body: %s', request.get_data())
    app.logger.debug('Args: %s', dict(request.args))

@app.after_request
def log_response_info(response):
    app.logger.debug('Response Status: %s', response.status)
    return response
```

**Check configuration:**

```bash
flask shell
>>> from flask import current_app
>>> current_app.config['SQLALCHEMY_DATABASE_URI']
>>> current_app.url_map
>>> current_app.extensions
```

**Database state:**

```python
# In flask shell
>>> from app import db
>>> db.session.execute(text("SELECT 1")).fetchone()  # Test connection
>>> User.query.count()
>>> db.engine.pool.status()  # Connection pool status
```

### Phase 3: Hypothesize and Test

**Form hypotheses based on error patterns:**

| Error Pattern | Likely Cause | Test |
|---------------|--------------|------|
| 404 on valid route | Blueprint not registered | Check `app.url_map` |
| 500 with no traceback | Error before request context | Check `create_app()` |
| DetachedInstanceError | Lazy load outside session | Add `lazy='joined'` |
| Connection refused | DB not running | Test connection string |

**Test hypotheses systematically:**

```python
# Hy

Related in Code Review