Fix pydantic ValidationError on startup

A ValidationError when your app boots is pydantic working exactly as designed — it caught a configuration problem before the first request. The fix is to read the error, not to suppress it. This page decodes the common cases, extending Strict Mode & Type Coercion.

Problem 1: swallowing the error

# ANTI-PATTERN: hides the one error that should be fatal
try:
    settings = Settings()
except ValidationError:
    settings = Settings.model_construct()   # boots with INVALID config

model_construct skips validation, so the app runs with broken configuration — far worse than crashing.

Problem 2: not reading the field path

# The error tells you exactly what's wrong — read it.
2 validation errors for Settings
database_url
  Field required [type=missing]
port
  Input should be a valid integer [type=int_parsing], input_value='8O80'

database_url is unset; port has a letter O instead of a zero. Both are named precisely.

Secure implementation

# config/bootstrap.py
import sys
from pydantic import ValidationError
from config.settings import Settings

def load() -> Settings:
    try:
        return Settings()
    except ValidationError as exc:
        # Report which fields failed (names only) and exit non-zero.
        for err in exc.errors():
            loc = ".".join(str(p) for p in err["loc"])
            print(f"config error: {loc}: {err['msg']}", file=sys.stderr)
        sys.exit(1)            # fail fast; never boot on invalid config

settings = load()

exc.errors() gives a structured list of loc (field path) and msg. Log those, exit non-zero, and keep the fail-fast contract. Never unwrap secret values into the log.

Gotchas & version-specific behaviour

  • [type=missing] means a required variable is unset — check the name and the environment.
  • [type=int_parsing] / [type=bool_parsing] means a value is the wrong shape; inspect input_value.
  • extra_forbidden means a variable is set that the model does not declare — a typo or a stale key.
  • Print field names only; err["input"] may contain a secret, so do not log it for secret fields.

Production parity checklist

  • The error is logged with field paths and the process exits non-zero.
  • No model_construct fallback that boots on invalid config.
  • CI constructs Settings() so these errors surface before deploy.
  • Secret values are never printed in the error handler.
  • extra="forbid" is kept so typos appear as extra_forbidden.

Conclusion

A startup ValidationError is a precise bug report — read the loc, fix the variable, and preserve the fail-fast exit. For the underlying coercion rules behind *_parsing errors, see Strict Mode & Type Coercion.