From 17b4fdb3b779392fcaa3e72a3f39a0ef12cb0fe7 Mon Sep 17 00:00:00 2001 From: vivekvar-dl Date: Sat, 21 Mar 2026 03:14:35 +0000 Subject: [PATCH] fix: treat empty OPENAI_BASE_URL same as None for default fallback Fixes #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. --- fix_base_url.py | 45 +++++++++++++++++++++++++++++++++++++++++++ src/openai/_client.py | 8 ++++++-- 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 fix_base_url.py diff --git a/fix_base_url.py b/fix_base_url.py new file mode 100644 index 0000000000..a480faed90 --- /dev/null +++ b/fix_base_url.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Fix script for issue #2927: empty OPENAI_BASE_URL should fallback to default""" + +file_path = "src/openai/_client.py" + +with open(file_path, 'r') as f: + lines = f.readlines() + +modified_lines = [] +i = 0 +while i < len(lines): + line = lines[i] + + # Look for the pattern: + # if base_url is None: + # base_url = os.environ.get("OPENAI_BASE_URL") + # if base_url is None: + # base_url = f"https://api.openai.com/v1" + + if 'if base_url is None:' in line and i+1 < len(lines): + next_line = lines[i+1] + if 'base_url = os.environ.get("OPENAI_BASE_URL")' in next_line: + # This is the first "if base_url is None" + # Keep it as is + modified_lines.append(line) + modified_lines.append(next_line) + i += 2 + + # Now check if the next line is the second "if base_url is None" + if i < len(lines) and 'if base_url is None:' in lines[i]: + # Replace this second check with "if not base_url:" + indent = lines[i][:lines[i].index('if')] + modified_lines.append(f"{indent}# Treat empty string same as None to allow fallback to default\n") + modified_lines.append(f"{indent}# Fixes #2927: export OPENAI_BASE_URL=\"\" should not prevent default URL\n") + modified_lines.append(f"{indent}if not base_url:\n") + i += 1 + continue + + modified_lines.append(line) + i += 1 + +with open(file_path, 'w') as f: + f.writelines(modified_lines) + +print("✅ Fixed both occurrences (sync and async clients)") diff --git a/src/openai/_client.py b/src/openai/_client.py index aadf3601f2..9d0361e815 100644 --- a/src/openai/_client.py +++ b/src/openai/_client.py @@ -162,7 +162,9 @@ def __init__( if base_url is None: base_url = os.environ.get("OPENAI_BASE_URL") - if base_url is None: + # Treat empty string same as None to allow fallback to default + # Fixes #2927: export OPENAI_BASE_URL="" should not prevent default URL + if not base_url: base_url = f"https://api.openai.com/v1" super().__init__( @@ -537,7 +539,9 @@ def __init__( if base_url is None: base_url = os.environ.get("OPENAI_BASE_URL") - if base_url is None: + # Treat empty string same as None to allow fallback to default + # Fixes #2927: export OPENAI_BASE_URL="" should not prevent default URL + if not base_url: base_url = f"https://api.openai.com/v1" super().__init__(