BerriAI/litellm · error · HTTPException

Invalid Authorization header format. Expected: Bearer <token

Error message

Invalid Authorization header format. Expected: Bearer <token>

What it means

A type guard in async fine-tuning job creation: when _is_async=True, the resolved client must be an AsyncOpenAI (or AsyncAzureOpenAI). If a synchronous OpenAI/AzureOpenAI client was supplied (typical when a user passes client=OpenAI(...) but calls the async entrypoint, or when get_openai_client defaulted to a sync client), this ValueError prevents an awaited call on a non-awaitable. It is a client-type mismatch error raised locally.

Source

Thrown at cookbook/mock_guardrail_server/mock_bedrock_guardrail_server.py:187

    Returns:
        The token if valid

    Raises:
        HTTPException: If token is missing or invalid
    """
    if authorization is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Missing Authorization header",
            headers={"WWW-Authenticate": "Bearer"},
        )

    # Check if it's a Bearer token
    parts = authorization.split()
    print(f"parts: {parts}")
    if len(parts) != 2 or parts[0].lower() != "bearer":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid Authorization header format. Expected: Bearer <token>",
            headers={"WWW-Authenticate": "Bearer"},
        )

    token = parts[1]

    # Verify token
    if token != GUARDRAIL_CONFIG.bearer_token:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Invalid bearer token",
        )

    return token


# ============================================================================

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass an AsyncOpenAI client: client = AsyncOpenAI(api_key=...) when using async fine-tuning.
  2. Or drop the custom client and let litellm build the async client from OPENAI_API_KEY.
  3. Or use the synchronous create_fine_tuning_job() if you cannot switch clients.

Example fix

# before
client = OpenAI(api_key=key)
job = await litellm.acreate_fine_tuning_job(..., client=client)  # raises

# after
client = AsyncOpenAI(api_key=key)
job = await litellm.acreate_fine_tuning_job(..., client=client)
Defensive patterns

Strategy: type-guard

Validate before calling

from openai import AsyncOpenAI

def is_async_client(client: object) -> bool:
    return isinstance(client, AsyncOpenAI)

Type guard

from openai import AsyncOpenAI, AsyncAzureOpenAI

def is_usable_async_client(client: object) -> bool:
    return isinstance(client, (AsyncOpenAI, AsyncAzureOpenAI))

Try / catch

try:
    job = await litellm.acreate_fine_tuning_job(..., client=client)
except ValueError as e:
    if "AsyncOpenAI" in str(e):
        from openai import AsyncOpenAI
        job = await litellm.acreate_fine_tuning_job(..., client=AsyncOpenAI(api_key=key))
    else:
        raise

Prevention

When it happens

Trigger: Calling the async fine-tuning path (e.g. await litellm.acreate_fine_tuning_job(...) or _is_async=True) while passing a synchronous OpenAI() client, or constructing the handler in a way that resolves to a sync client for an async operation.

Common situations: Porting sync example code to asyncio and forgetting to swap OpenAI() for AsyncOpenAI(); shared client factories returning sync clients for both paths; copy-pasting sync client setup into FastAPI async endpoints.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/f4841cb6b22824f4. Report an issue: GitHub.