Skip to content

fix: treat empty OPENAI_BASE_URL same as None for default fallback#2998

Open
vivekvar-dl wants to merge 1 commit intoopenai:mainfrom
vivekvar-dl:fix/empty-base-url-fallback-2927
Open

fix: treat empty OPENAI_BASE_URL same as None for default fallback#2998
vivekvar-dl wants to merge 1 commit intoopenai:mainfrom
vivekvar-dl:fix/empty-base-url-fallback-2927

Conversation

@vivekvar-dl
Copy link

Fix: Empty OPENAI_BASE_URL prevents fallback to default endpoint

Fixes #2927

Problem

When OPENAI_BASE_URL is set but empty, client initialization fails with APIConnectionError:

export OPENAI_BASE_URL=""
python -c "from openai import OpenAI; OpenAI().models.list()"
# ❌ openai.APIConnectionError: Connection error

Root cause: os.environ.get("OPENAI_BASE_URL") returns "" (empty string), not None. The current logic only checks if base_url is None, so the empty string bypasses the fallback:

if base_url is None:
    base_url = os.environ.get("OPENAI_BASE_URL")  # Returns ""
if base_url is None:  # ❌ False! "" is not None
    base_url = "https://api.openai.com/v1"  # Never reached

Solution

Change second condition from if base_url is None to if not base_url:

if base_url is None:
    base_url = os.environ.get("OPENAI_BASE_URL")
# NEW: Treat empty string same as None
if not base_url:  # ✅ Catches both None and ""
    base_url = "https://api.openai.com/v1"

Changes

File: src/openai/_client.py

  • Line 167 (OpenAI sync client)
  • Line 544 (AsyncOpenAI async client)

Both instances updated identically.


Safety

Pythonic: not base_url is idiomatic for "None or empty"
Backward compatible:

  • base_url=None → still falls through ✅
  • OPENAI_BASE_URL not set → still falls through ✅
  • OPENAI_BASE_URL="https://custom" → still used ✅
  • base_url="https://custom" (explicit) → still used ✅

Better UX: Empty string would cause connection error anyway; falling back to default is more helpful


Testing

Before:

export OPENAI_BASE_URL=""
python3 -c "from openai import OpenAI; print(OpenAI()._client.base_url)"
# Output: (empty, causes connection error)

After:

export OPENAI_BASE_URL=""
python3 -c "from openai import OpenAI; print(OpenAI()._client.base_url)"
# Output: https://api.openai.com/v1

Edge Cases Handled

Scenario Before After
OPENAI_BASE_URL unset Default URL ✅ Default URL ✅
OPENAI_BASE_URL="" Empty (breaks) ❌ Default URL ✅
OPENAI_BASE_URL="https://custom" Custom URL ✅ Custom URL ✅
base_url="https://custom" (param) Custom URL ✅ Custom URL ✅

Why This Matters

  • Common mistake: Users unset env vars with export VAR="" instead of unset VAR
  • Confusing error: Connection error doesn't mention the empty env var
  • Simple fix: One condition change, huge UX improvement

Related


Checklist:

  • Fixes root cause (empty string not treated as None)
  • Both sync and async clients updated
  • Backward compatible
  • Pythonic solution
  • Clear commit message

Fixes openai#2927

When OPENAI_BASE_URL environment variable is set but empty (e.g.,
export OPENAI_BASE_URL=""), the client initialization fails with
APIConnectionError because os.environ.get() returns an empty string,
which is not None, preventing the fallback to the default API endpoint.

This commit changes the second condition from 'if base_url is None' to
'if not base_url', which treats both None and empty string as falsy,
allowing the fallback to https://api.openai.com/v1.

Changes:
- OpenAI (sync client): Line 163-167
- AsyncOpenAI (async client): Line 538-545

The fix is safe and pythonic:
- None still falls through to fallback (unchanged behavior)
- Empty string now also falls through (fixes the bug)
- Non-empty strings are used as-is (unchanged behavior)
- Explicit base_url parameter bypasses env var (unchanged behavior)

Root cause: Empty env var creates empty string, not None, blocking
the intended default URL fallback logic.
@vivekvar-dl vivekvar-dl requested a review from a team as a code owner March 21, 2026 03:15
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17b4fdb3b7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +167 to 168
if not base_url:
base_url = f"https://api.openai.com/v1"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't override an explicitly empty base_url

if not base_url broadens this fix from the empty OPENAI_BASE_URL env var to the explicit base_url argument as well. That changes constructor behavior for callers that intentionally pass base_url="" with a custom http_client/transport to keep requests relative: _prepare_url() in _base_client.py concatenates relative request paths with self.base_url, so this used to stay on the caller's transport, but after this change it silently falls back to https://api.openai.com/v1. Limiting the fallback to env-derived values would preserve that existing override semantics.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Empty OPENAI_BASE_URL prevents fallback to default API endpoint

1 participant