hermes - 💡(How to fix) Fix [Bug]: auxiliary vision returns 401 when provider has custom base_url — API key resolves to no-key-required [1 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

  1. Error: 401 - Invalid API Key

Root Cause

In agent/auxiliary_client.py _resolve_task_provider_model() line ~4529:

if base_url:
    return "custom", resolved_model, base_url, api_key, resolved_api_mode

This always returns provider="custom" when base_url is passed as an argument, even when a named provider was explicitly requested. The config path (line ~4539) correctly preserves the provider — the argument path does not.

The double-call pattern in resolve_vision_provider_client triggers this: it calls _resolve_task_provider_model once to read config (correct), then the resolved base_url is passed as an argument on the second call (incorrect — hits the buggy early-return).

Scope: Affects any named provider with custom base_url in auxiliary config (ZAI, Kimi, Xiaomi, MiniMax, etc.), not just xiaomi.

Fix Action

Fixed

Code Example

auxiliary:
  vision:
    provider: xiaomi
    model: mimo-v2-omni
    base_url: https://token-plan-ams.xiaomimimo.com/v1

---

if base_url:
    return "custom", resolved_model, base_url, api_key, resolved_api_mode

---

if base_url:
    resolved_provider = provider if provider and provider not in ("", "auto") else "custom"
    return resolved_provider, resolved_model, base_url, api_key, resolved_api_mode
RAW_BUFFERClick to expand / collapse

Bug Description

When auxiliary.vision is configured with a named provider (e.g. xiaomi) and a custom base_url, the vision_analyze tool returns HTTP 401 "Invalid API Key" because _resolve_task_provider_model() replaces the named provider with "custom", causing resolve_provider_client() to only check OPENAI_API_KEY (which doesn't exist) and fall back to the placeholder "no-key-required".

The provider's actual API key (e.g. XIAOMI_API_KEY from .env) is never resolved.

Steps to Reproduce

  1. Configure config.yaml:
auxiliary:
  vision:
    provider: xiaomi
    model: mimo-v2-omni
    base_url: https://token-plan-ams.xiaomimimo.com/v1
  1. Set XIAOMI_API_KEY= in ~/.hermes/.env
  2. Call vision_analyze with any image
  3. Error: 401 - Invalid API Key

Expected Behavior

vision_analyze should resolve the provider-specific API key from the credential pool.

Actual Behavior

Client is created with api_key="no-key-required" because the named provider identity is lost during resolution.

Root Cause

In agent/auxiliary_client.py _resolve_task_provider_model() line ~4529:

if base_url:
    return "custom", resolved_model, base_url, api_key, resolved_api_mode

This always returns provider="custom" when base_url is passed as an argument, even when a named provider was explicitly requested. The config path (line ~4539) correctly preserves the provider — the argument path does not.

The double-call pattern in resolve_vision_provider_client triggers this: it calls _resolve_task_provider_model once to read config (correct), then the resolved base_url is passed as an argument on the second call (incorrect — hits the buggy early-return).

Scope: Affects any named provider with custom base_url in auxiliary config (ZAI, Kimi, Xiaomi, MiniMax, etc.), not just xiaomi.

Related Issues

  • #16389 (merged) — fixed routing in resolve_vision_provider_client but missed upstream bug in _resolve_task_provider_model
  • #33333 — similar credential-dropping for custom providers in cron
  • #27555 — vision fallback chain broken (P1, different root cause)

Proposed Fix

Preserve named provider identity in the base_url argument path:

if base_url:
    resolved_provider = provider if provider and provider not in ("", "auto") else "custom"
    return resolved_provider, resolved_model, base_url, api_key, resolved_api_mode

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix [Bug]: auxiliary vision returns 401 when provider has custom base_url — API key resolves to no-key-required [1 pull requests]