hermes - 💡(How to fix) Fix bug: _extract_pricing crashes on list-typed pricing values, causing context_length fallback to 256K [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…

_extract_pricing() in agent/model_metadata.py crashes with TypeError: unhashable type: 'list' when a provider's /v1/models endpoint returns pricing values as lists of objects (e.g. zenmux.ai). This causes fetch_endpoint_model_metadata() to return an empty dict, which makes get_model_context_length() fall through to DEFAULT_FALLBACK_CONTEXT (256K) instead of the correct value — even when the endpoint clearly reports context_length: 1000000 and hardcoded defaults also specify 1M.

Root Cause

agent/model_metadata.py line 596:

python
if alias in normalized and normalized[alias] not in {None, ""}:


normalized[alias] can be a list (e.g. zenmux returns "completion": [{"value": 2, "unit": "perMTokens", ...}]). Lists are unhashable, so list not in {None, ""} raises TypeError.

This exception is caught by the outer except Exception in the candidate loop, which silently moves to the next candidate URL. When all candidates fail (the 2nd candidate /api/models returns HTML, not JSON), the function caches an empty dict and returns {}.

Impact

Any custom endpoint whose /v1/models response includes list-typed pricing fields will have its model metadata discarded. The function then exits early at the custom-endpoint branch with DEFAULT_FALLBACK_CONTEXT — the hardcoded defaults (step 8) and OpenRouter cache (step 6) are never reached because the custom-endpoint path has its own early-return fallback.

Reproduction

python
from agent.model_metadata import get_model_context_length

ctx = get_model_context_length(
    model='deepseek/deepseek-v4-pro',
    base_url='https://zenmux.ai/api/v1',
    api_key='<valid-zenmux-key>',
    provider='custom:zenmux',
)
Returns: 256000 (DEFAULT_FALLBACK_CONTEXT)
Expected: 1000000


Fix

One-line change — add a type guard before the membership check:

diff
-                if alias in normalized and normalized[alias] not in {None, ""}:
+                if alias in normalized and isinstance(normalized[alias], (int, float, str)) and normalized[alias] not in {None, ""}:


Environment

- Hermes Agent v0.13.0 (2026.5.7) and latest origin/main
- Python 3.11
- Reproduced with zenmux.ai

Error Message

This exception is caught by the outer except Exception in the candidate loop, which silently moves to the next candidate URL. When all candidates fail (the 2nd candidate /api/models returns HTML, not JSON), the function caches an empty dict and returns {}.

Root Cause

Root Cause

Fix Action

Fixed

RAW_BUFFERClick to expand / collapse

Summary

_extract_pricing() in agent/model_metadata.py crashes with TypeError: unhashable type: 'list' when a provider's /v1/models endpoint returns pricing values as lists of objects (e.g. zenmux.ai). This causes fetch_endpoint_model_metadata() to return an empty dict, which makes get_model_context_length() fall through to DEFAULT_FALLBACK_CONTEXT (256K) instead of the correct value — even when the endpoint clearly reports context_length: 1000000 and hardcoded defaults also specify 1M.

Root Cause

agent/model_metadata.py line 596:

python
if alias in normalized and normalized[alias] not in {None, ""}:


normalized[alias] can be a list (e.g. zenmux returns "completion": [{"value": 2, "unit": "perMTokens", ...}]). Lists are unhashable, so list not in {None, ""} raises TypeError.

This exception is caught by the outer except Exception in the candidate loop, which silently moves to the next candidate URL. When all candidates fail (the 2nd candidate /api/models returns HTML, not JSON), the function caches an empty dict and returns {}.

Impact

Any custom endpoint whose /v1/models response includes list-typed pricing fields will have its model metadata discarded. The function then exits early at the custom-endpoint branch with DEFAULT_FALLBACK_CONTEXT — the hardcoded defaults (step 8) and OpenRouter cache (step 6) are never reached because the custom-endpoint path has its own early-return fallback.

Reproduction

python
from agent.model_metadata import get_model_context_length

ctx = get_model_context_length(
    model='deepseek/deepseek-v4-pro',
    base_url='https://zenmux.ai/api/v1',
    api_key='<valid-zenmux-key>',
    provider='custom:zenmux',
)
Returns: 256000 (DEFAULT_FALLBACK_CONTEXT)
Expected: 1000000


Fix

One-line change — add a type guard before the membership check:

diff
-                if alias in normalized and normalized[alias] not in {None, ""}:
+                if alias in normalized and isinstance(normalized[alias], (int, float, str)) and normalized[alias] not in {None, ""}:


Environment

- Hermes Agent v0.13.0 (2026.5.7) and latest origin/main
- Python 3.11
- Reproduced with zenmux.ai

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: _extract_pricing crashes on list-typed pricing values, causing context_length fallback to 256K [1 pull requests]