tiangolo/fastapi · error · ValueError

Invalid ID format, it must start with "isbn-" or "imdb-"

Error message

Invalid ID format, it must start with "isbn-" or "imdb-"

What it means

A ValueError raised inside an AfterValidator (check_valid_id) attached to the `id` query parameter. FastAPI/Pydantic converts validator ValueErrors into a 422 RequestValidationError response. The validator requires the id to start with 'isbn-' or 'imdb-'. This shows constraining query-string format via Pydantic AfterValidator.

Solutions

  1. Prefix the id correctly, e.g. GET /items/?id=isbn-9781529046137 or GET /items/?id=imdb-tt0371724.
  2. Drop the id parameter to get a random valid item.
  3. If new prefixes should be allowed, update the tuple passed to str.startswith.

Example fix

// before
def check_valid_id(id: str):
    if not id.startswith(("isbn-", "imdb-")):
        raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
    return id
// after (add prefix and clearer message)
ALLOWED = ("isbn-", "imdb-")
def check_valid_id(id: str):
    if not id.startswith(ALLOWED):
        raise ValueError(f'Invalid ID format, it must start with one of {ALLOWED}')
    return id
Defensive patterns

Strategy: validation

Validate before calling

def check_valid_id(id: str):
    if not id.startswith(('isbn-', 'imdb-')):
        raise ValueError('bad id')
check_valid_id(id)  # raises locally before the request

Type guard

def is_valid_id(id: str) -> bool:
    return id.startswith(('isbn-', 'imdb-'))

Try / catch

resp = requests.get('http://localhost:8000/items/', params={'id': id})
if resp.status_code == 422:
    print('Invalid id format:', resp.json()['detail'])

Prevention

When it happens

Trigger: GET /items/?id=<value> where <value> does not start with 'isbn-' or 'imdb-'. Omitting id entirely is allowed (defaults to None, then random).

Common situations: Enforcing ID prefixes / formats on query params. Developers hit 422 when they pass a raw id without the required prefix or with wrong casing.

Related errors


AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11). Data as JSON: /api/errors/9ef8f6ae1df13759. Report an issue: GitHub.

Appendix: source

Thrown at docs_src/query_params_str_validations/tutorial015_an_py310.py:18

import random
from typing import Annotated

from fastapi import FastAPI
from pydantic import AfterValidator

app = FastAPI()

data = {
    "isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
    "imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
    "isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}


def check_valid_id(id: str):
    if not id.startswith(("isbn-", "imdb-")):
        raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
    return id


@app.get("/items/")
async def read_items(
    id: Annotated[str | None, AfterValidator(check_valid_id)] = None,
):
    if id:
        item = data.get(id)
    else:
        id, item = random.choice(list(data.items()))
    return {"id": id, "name": item}

View on GitHub (pinned to 3e8d1526d8)