Skip to content

fix(agent): parse OpenRouter/Nous output-cap errors to prevent infinite reset loop - #38667

Closed
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/parse-openrouter-output-cap-error
Closed

fix(agent): parse OpenRouter/Nous output-cap errors to prevent infinite reset loop#38667
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/parse-openrouter-output-cap-error

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds OpenRouter / Nous Research inference error format support to parse_available_output_tokens_from_error(). Previously, the function only recognized Anthropic's "available_tokens" keyword. When using OpenRouter-compatible providers, errors with "N in the output" format were misclassified as prompt-too-long errors, causing infinite session reset loops when max_tokens exceeded the available context.

Related Issue

Fixes #38652

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • agent/model_metadata.py: Extended parse_available_output_tokens_from_error() to detect OpenRouter/Nous error format ("N of text input, M of tool input, K in the output") and calculate available output tokens as context_length - text_input - tool_input. Refactored detection into two phases: (1) identify error format, (2) extract available tokens.
  • tests/test_ctx_halving_fix.py: Added 4 tests covering the OpenRouter/Nous format: canonical format with all components, format without tool input, format with only text input, and format without context length (returns None).

How to Test

  1. Run pytest tests/test_ctx_halving_fix.py -v — all 31 tests should pass (4 new + 27 existing)
  2. Run pytest tests/agent/test_model_metadata.py -v — all 93 tests should pass (no regressions)
  3. Manual verification: configure a provider with max_tokens exceeding the context window and confirm the error recovery loop no longer occurs

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Code Intelligence

  • Analyzed: parse_available_output_tokens_from_error in agent/model_metadata.py (callers: conversation_loop.py:2989, anthropic_adapter.py:2119)
  • Blast radius: LOW — pure parsing function, no side effects; callers already handle None return gracefully
  • Related patterns: parse_context_limit_from_error() (sibling function, same file), _ephemeral_max_output_tokens (consumer in conversation loop)

…te reset loop

The parse_available_output_tokens_from_error() function only recognized
Anthropic's 'available_tokens' keyword. OpenRouter/Nous providers return
errors with 'N in the output' format, which was misclassified as a
prompt-too-long error. This caused infinite session reset loops when
max_tokens exceeded the available context window.

Added regex-based extraction that parses context_length, text_input, and
tool_input components from the OpenRouter error format, then calculates
available output tokens as context_length - text_input - tool_input.

Fixes NousResearch#38652
@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/openrouter OpenRouter aggregator provider/nous Nous Research API (OAuth) labels Jun 4, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #38659 — both fix #38652 by extending parse_available_output_tokens_from_error() in agent/model_metadata.py to parse the OpenRouter/Nous "N in the output" error format. Same root cause and same code path; maintainers should pick one.

@liuhao1024

Copy link
Copy Markdown
Contributor Author

Thanks for the flag @alt-glitch. Comparing the two PRs:

The production code changes are functionally equivalent — both extend parse_available_output_tokens_from_error() to handle the OpenRouter/Nous "N in the output" format. #38659's approach is more minimal, which is generally preferred for upstream contributions. Closing in favor of #38659.

@liuhao1024 liuhao1024 closed this Jun 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P1 High — major feature broken, no workaround provider/nous Nous Research API (OAuth) provider/openrouter OpenRouter aggregator type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: parse_available_output_tokens_from_error() misses OpenRouter/Nous "in the output" format — causes infinite auto-reset loop

2 participants