Bug: OpenRouter @provider pin silently lost — routes to wrong backend (e.g. Alibaba instead of Novita)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19.9k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 30
Description
Bug: OpenRouter @provider pin silently lost — routes to wrong backend (e.g. Alibaba instead of Novita)
Summary
When using /model z-ai/glm-5.2@Novita, jcode silently routes to a different OpenRouter backend provider (e.g. Alibaba) instead of the user's pinned choice. The @provider pin is lost in multiple code paths, and the default allow_fallbacks=true lets OpenRouter fall back to whatever provider it ranks first.
Reproduction
- Have
OPENROUTER_API_KEYconfigured - Start jcode
- Run
/model z-ai/glm-5.2@Novita - Send a message
- Check the session header — it shows
via Alibabainstead ofvia Novita
Root Cause (confirmed via runtime logs)
Four bugs combine:
-
OpenRouterProvider::fork()resetsprovider_pintoNoneinstead of copying from the parent. Forked providers lose the pin entirely. -
provider.model()returns the bare model id (z-ai/glm-5.2) without the@Novitapin. Session save/restore paths all usedprovider.model(), so sessions restored without the pin. OpenRouter then used endpoint ranking, Alibaba served first, and the observed session pin locked onto Alibaba withallow_fallbacks=false. -
handle_auth_changedreplaces the OpenRouter runtime with a fresh one (losing the pin) whenreconcile_auth_if_provider_missingtriggerson_auth_changed(). -
Explicit
@providerpins allowed fallbacks by default —@Novita(without!) setallow_fallbacks=true, so OpenRouter could fall back to a different provider. Once Alibaba served a request, it got observed-pinned and locked the session.
Log evidence
# First request: no pin, endpoint ranking (Alibaba first)
OpenRouter routing: model=z-ai/glm-5.2, order=Some(["CoreWeave", "Cloudflare", ..., "Alibaba", ..., "Novita", ...]), allow_fallbacks=true
# Subsequent requests: locked to Alibaba via observed pin
OpenRouter routing: model=z-ai/glm-5.2, order=Some(["Alibaba"]), allow_fallbacks=false
Fix
A fix is available on my fork: https://github.com/ewheels44/ecode/pull/1
Branch: fix/openrouter-provider-pin (3 commits, cherry-picked clean from upstream/master)
Changes:
OpenRouterProvider::fork()now copiesprovider_pinfrom parent- Added
explicit_provider_pin_for_current_model()onMultiProviderto reconstruct fullmodel@pinspec - All session save/restore paths use
provider_model()which includes the pin handle_auth_changedre-applies model+pin when replacing the OpenRouter runtime- Explicit
@providerpins now always setallow_fallbacks=false
After fix:
OpenRouter routing: model=z-ai/glm-5.2, order=Some(["Novita"]), allow_fallbacks=false
Environment
- jcode v0.61.14-dev
- macOS aarch64
- OpenRouter API key configured
- Affects all OpenRouter models with
@providersyntax
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with OpenRouterProvider::fork(), MultiProvider::explicit_provider_pin_for_current_model(), the session save/restore paths, and handle_auth_changed. Compare the behavior with the fix described on the linked fork, then verify that an explicit @provider request remains pinned through forking, persistence, and authentication changes, with fallbacks disabled.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100