affaan-m/ECC · warning · NotFoundError

User not found: {user_id}

Error message

User not found: {user_id}

What it means

A NotFoundError (subclass of AppError) raised by get_user() when db.find_user(user_id) returns a falsy value. It indicates the requested user does not exist in the data store. It is part of a custom exception hierarchy (AppError -> NotFoundError) intended for domain-level control flow.

Source

Thrown at skills/python-patterns/SKILL.md:194

```python
class AppError(Exception):
    """Base exception for all application errors."""
    pass

class ValidationError(AppError):
    """Raised when input validation fails."""
    pass

class NotFoundError(AppError):
    """Raised when a requested resource is not found."""
    pass

# Usage
def get_user(user_id: str) -> User:
    user = db.find_user(user_id)
    if not user:
        raise NotFoundError(f"User not found: {user_id}")
    return user
```

## Context Managers

### Resource Management

```python
# Good: Using context managers
def process_file(path: str) -> str:
    with open(path, 'r') as f:
        return f.read()

# Bad: Manual resource management
def process_file(path: str) -> str:
    f = open(path, 'r')
    try:
        return f.read()

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Confirm the user_id exists in the data source with a direct query.
  2. Check whether a soft-delete filter or tenant scope is excluding the row.
  3. Handle the race: re-fetch or use a transaction if a concurrent delete is possible.
  4. Catch NotFoundError at the handler/controller layer and map it to an HTTP 404 response rather than a 500.

Example fix

# before
user = db.find_user(user_id)
if not user:
    raise NotFoundError(f"User not found: {user_id}")

# after: distinguish not-found from deleted at the boundary
user = db.find_user(user_id, include_deleted=False)
if user is None:
    existing = db.find_user(user_id, include_deleted=True)
    if existing is not None:
        raise GoneError(f"User deleted: {user_id}")
    raise NotFoundError(f"User not found: {user_id}")
Defensive patterns

Strategy: try-catch

Validate before calling

def user_exists(user_id: str) -> bool:
    return db.find_user(user_id) is not None

if not user_exists(user_id):
    return http_response(404, {"error": "user not found"})

Type guard

null

Try / catch

from myapp.errors import NotFoundError
try:
    user = get_user(user_id)
except NotFoundError:
    return respond_404(user_id)
else:
    return respond_200(user)

Prevention

When it happens

Trigger: Calling get_user(user_id) with an id that has no matching row; the database lookup returned None, an empty result, or an empty ORM object; the id was deleted between lookup and access.

Common situations: Stale references in a URL after a user is deleted; race condition between delete and read; typo in an id passed from a route parameter; soft-deleted records excluded by a default query filter.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/7ec3f3c290ec341e. Report an issue: GitHub.