Skip to content

fix: empty/whitespace credentials should raise MissingCredentialsError #184

Description

@Kamilbenkirane

Bug

When a provider API key is set to an empty string or whitespace-only value, the SDK sends an invalid Authorization: Bearer header instead of raising MissingCredentialsError.

Root Cause

get_credentials() and has_credential() in credentials.py only check if credential is None. Pydantic BaseSettings converts empty string env vars ("") to SecretStr(''), which passes the is not None check.

How to Reproduce

Any of these will trigger the bug:

# Empty .env value
HF_TOKEN=

# Empty shell export
export OPENAI_API_KEY=""

# Whitespace-only
export ANTHROPIC_API_KEY="   "
from celeste import create_client, Modality

# Instead of MissingCredentialsError, this sends "Authorization: Bearer "
# and crashes with: httpx.LocalProtocolError: Illegal header value b'Bearer '
client = create_client(modality=Modality.TEXT, model="gpt-4")
await client.generate(prompt="Hi")

Affected Code

  • src/celeste/credentials.pyget_credentials() (line ~118) and has_credential() (line ~145) only check is not None
  • src/celeste/auth.pyAuthHeader.convert_to_secret() strips whitespace but doesn't reject empty result

Impact

  • All providers using the AuthHeader path are affected (OpenAI, Anthropic, Groq, HuggingFace, Mistral, etc.)
  • Ollama is NOT affected — it uses NoAuth which bypasses AuthHeader entirely
  • GitHub Actions CI is a common trigger: ${{ secrets.MISSING_SECRET }} resolves to "" when the secret doesn't exist
  • User experience degrades: cryptic httpx.LocalProtocolError instead of clear MissingCredentialsError

Proposed Fix

  1. get_credentials() — reject empty/whitespace secrets with MissingCredentialsError
  2. has_credential() — treat empty/whitespace as "not configured"
  3. Update test_whitespace_credentials in tests/unit_tests/test_credentials.py to expect the new behavior

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions