Description
When using the hermes model interactive picker to switch to a model under custom_providers:, the CLI can write the literal string custom to model.provider in config.yaml instead of the actual provider name (e.g. xiaomi-coding).
This causes every subsequent session to fail with:
✗ Unknown provider 'custom'. Check 'hermes model' for available providers, or define it in config.yaml under 'providers:'.
Root Cause
In hermes_cli/model_switch.py list_authenticated_providers() (lines 1466-1472), slug assignment logic:
if current_base_url and api_url == current_base_url.strip().rstrip('/'):
slug = current_provider or custom_provider_slug(display_name)
else:
slug = custom_provider_slug(display_name)
When a prior failed switch already wrote provider: custom to config.yaml, current_provider = 'custom'. On the next picker run, if current_base_url matches, slug = current_provider = 'custom' (literal). The picker passes 'custom' as explicit_provider to switch_model().
Then resolve_provider_full('custom', ...) checks:
- Built-in providers → no match
providers: dict → empty, no match
custom_providers → slug is custom:xiaomi-coding, doesn't match bare 'custom'
- Returns None → error at model_switch.py:654
Config State That Triggers It
model:
provider: custom # ← should be 'xiaomi-coding' or 'custom:xiaomi-coding'
base_url: ''
custom_providers:
- name: xiaomi-coding
base_url: https://token-plan-sgp.xiaomimimo.com/v1
Suggested Fix
In resolve_provider_full() or the slug assignment logic, either:
- Reject bare
'custom' as a valid slug — always require the full custom:<name> format
- When
current_provider == 'custom', look up the matching custom_provider by base_url and use the proper slug
- In startup validation (main.py:1570+), detect
provider: custom and auto-resolve to the correct custom_provider entry
Workaround
hermes config set model.provider <actual-provider-name>
Key Source Files
hermes_cli/model_switch.py — switch_model(), list_authenticated_providers()
hermes_cli/providers.py — resolve_provider_full(), resolve_custom_provider(), custom_provider_slug()
hermes_cli/main.py — startup provider validation (line 1570+)
Description
When using the
hermes modelinteractive picker to switch to a model undercustom_providers:, the CLI can write the literal stringcustomtomodel.providerin config.yaml instead of the actual provider name (e.g.xiaomi-coding).This causes every subsequent session to fail with:
Root Cause
In
hermes_cli/model_switch.pylist_authenticated_providers()(lines 1466-1472), slug assignment logic:When a prior failed switch already wrote
provider: customto config.yaml,current_provider = 'custom'. On the next picker run, ifcurrent_base_urlmatches,slug = current_provider = 'custom'(literal). The picker passes'custom'asexplicit_providertoswitch_model().Then
resolve_provider_full('custom', ...)checks:providers:dict → empty, no matchcustom_providers→ slug iscustom:xiaomi-coding, doesn't match bare'custom'Config State That Triggers It
Suggested Fix
In
resolve_provider_full()or the slug assignment logic, either:'custom'as a valid slug — always require the fullcustom:<name>formatcurrent_provider == 'custom', look up the matching custom_provider by base_url and use the proper slugprovider: customand auto-resolve to the correct custom_provider entryWorkaround
Key Source Files
hermes_cli/model_switch.py—switch_model(),list_authenticated_providers()hermes_cli/providers.py—resolve_provider_full(),resolve_custom_provider(),custom_provider_slug()hermes_cli/main.py— startup provider validation (line 1570+)