ATOM Documentation

← Back to App

Fix Summary: BYOK Fallback Logic for Legacy Provider IDs

**Date:** 2026-05-02

**Issue:** "No models available from dynamic pricing" + Team plan tier restriction bug

**Tenant:** Brennan Machinery (brennan)

Root Causes Identified

1. Team Plan Tier Restriction Bug ✅ FIXED

**Problem:** "team" plan was missing from MODEL_TIER_RESTRICTIONS and BYOK_ENABLED_PLANS

**Status:** Already fixed in core/cost_config.py (lines 36-48, 61)

2. Legacy Provider ID Migration Bug ✅ FIXED

**Problem:**

  • Database has MINIMAX_2_7_API_KEY but NOT MINIMAX_API_KEY
  • Provider registry had both "minimax" and "minimax_2_7" (stale duplicate)
  • Both providers expect MINIMAX_API_KEY in registry
  • But database lookup uses provider_id.upper() + "_API_KEY" pattern
  • No fallback mechanism to handle legacy provider IDs

**Impact:** Brennan's backfill crashed because:

  1. Client initialization skipped "minimax" provider (no MINIMAX_API_KEY in DB)
  2. Model ranking skipped "minimax/" models (provider not initialized)
  3. No models passed filters → "No models available from dynamic pricing"

Solution: Generic Fallback Logic ✅

Changes Made

1. Added Generic Fallback Logic in `get_tenant_api_key()`

**File:** core/byok_endpoints.py (lines 869-917)

**What it does:**

  • When primary lookup fails (e.g., MINIMAX_API_KEY not found)
  • Finds all providers sharing the same api_key_env_var
  • Tries alternate provider IDs (e.g., MINIMAX_2_7_API_KEY)
  • Returns first match found

**Example:**

# Provider: minimax
# Primary lookup: MINIMAX_API_KEY (not found)
# Fallback: Check MINIMAX_2_7_API_KEY (found!)
# Result: Returns key from MINIMAX_2_7_API_KEY

**Why this approach:**

  • Generic solution for all legacy provider ID migrations
  • Handles minimax_2_7minimax migration
  • Handles google_flashgoogle pattern (already special-cased)
  • Future-proof for other provider renames

2. Removed Stale `minimax_2_7` Provider

**Files:**

  • core/byok_endpoints.py (line 283-292) - Removed from provider registry
  • core/llm/byok_handler.py (line 590) - Removed from _LLM_PROVIDERS set
  • core/ai_onboarding_service.py (line 343) - Changed default to "minimax"

**Why:**

  • minimax_2_7 was a stale duplicate of minimax
  • Both used the same API key (MINIMAX_API_KEY)
  • Having both creates confusion and maintenance burden
  • Fallback logic allows existing databases with MINIMAX_2_7_API_KEY to work

3. TDD Tests Created

**File:** tests/test_byok_fallback_logic_tdd.py

**Tests:**

  1. test_fallback_finds_alternate_provider_keys - Verifies google_flash → GOOGLE_API_KEY fallback
  2. test_minimax_fallback_from_minimax_2_7_key - Verifies minimax → MINIMAX_2_7_API_KEY fallback
  3. test_removing_minimax_2_7_provider_still_works - Verifies safe removal of minimax_2_7

**Result:** All 3 tests pass ✅

Migration Path for Tenants

**What:** Tenants keep their existing MINIMAX_2_7_API_KEY

**How it works:**

  • Fallback logic automatically finds MINIMAX_2_7_API_KEY when looking for MINIMAX_API_KEY
  • No database changes required
  • Transparent to tenant

**Who benefits:** Brennan and any other tenants with MINIMAX_2_7_API_KEY

Option 2: Migrate to Canonical Key (Optional)

**What:** Add MINIMAX_API_KEY to database (same value as MINIMAX_2_7_API_KEY)

**How:**

INSERT INTO tenant_settings (tenant_id, setting_key, setting_value, created_at, updated_at)
VALUES (
    '31c06fc4-db22-4740-83ea-48ac14f25810',
    'MINIMAX_API_KEY',
    '<same_value_as_MINIMAX_2_7_API_KEY>',
    NOW(),
    NOW()
);

**Why:** Align with canonical provider ID (future-proof)

**Note:** Not required - fallback logic handles this automatically

Why This Approach Is Correct

❌ Wrong Approach: Special-Case `minimax_2_7`

if provider_id == "minimax_2_7":
    setting_key = "MINIMAX_API_KEY"  # Tech debt!

**Why wrong:**

  • Entrenches stale provider ID
  • Adds special case for every legacy migration
  • Doesn't solve the general problem

✅ Correct Approach: Generic Fallback Logic

# Find all providers sharing api_key_env_var
alternate_providers = [
    pid for pid, pconfig in self.providers.items()
    if pconfig.api_key_env_var == target_env_var and pid != provider_id
]

# Try each alternate provider's setting_key
for alt_provider_id in alternate_providers:
    alt_setting_key = f"{alt_provider_id.upper()}_API_KEY"
    # ... lookup and return if found

**Why correct:**

  • Generic solution for all provider ID migrations
  • Handles current issue (minimax_2_7minimax)
  • Handles future provider renames
  • No special cases per provider
  • Removes tech debt by deleting stale provider IDs

Verification

TDD Tests ✅

pytest tests/test_byok_fallback_logic_tdd.py -v
# Result: 3 passed

Code Review ✅

  • Fallback logic added to get_tenant_api_key()
  • minimax_2_7 removed from 3 locations
  • minimax is now the only MiniMax provider
  • Generic fallback handles all legacy migrations

Documentation ✅

  • Root cause analysis documented
  • Migration path for tenants
  • TDD tests verify behavior
  • Code comments explain fallback logic

Next Steps

  1. ✅ Deploy fallback logic to production
  2. ✅ Verify Brennan's backfill works with existing MINIMAX_2_7_API_KEY
  3. ⏳ Monitor logs to confirm fallback logic works
  4. ⏳ (Optional) Migrate tenants to canonical keys over time

**Modified:**

  • core/byok_endpoints.py - Added fallback logic, removed minimax_2_7 provider
  • core/llm/byok_handler.py - Removed minimax_2_7 from _LLM_PROVIDERS
  • core/ai_onboarding_service.py - Changed default to "minimax"

**Created:**

  • tests/test_byok_fallback_logic_tdd.py - TDD tests for fallback logic

**Documentation:**

  • docs/archive/logs/2026-05-02-minimax-fix-with-fallback-logic.md - This file
  • docs/archive/logs/2026-05-02-minimax-root-cause-verification.md - Previous analysis

Conclusion

The fix solves Brennan's issue with a **generic, future-proof solution**:

  • ✅ Team plan tier restrictions fixed
  • ✅ Generic fallback logic handles legacy provider IDs
  • ✅ Stale minimax_2_7 provider removed
  • ✅ TDD tests verify correctness
  • ✅ No database changes required for Brennan

**This is a code fix, not a data fix.** The fallback logic allows the system to work with existing database state while we gradually migrate to canonical keys.