1jehuang / 1jehuang/jcode

`jcode run` silently ignores JCODE_NAMED_PROVIDER_PROFILE and answers from the cloud default

Open
#1,121 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no bug priority: high triage: needs-decision triage: reproducible
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Source commit: 008abc44b1653efa65ccf98acb3b7236ce8507e6 (upstream master, chore(release): prepare v0.81.3)
Binary identity: jcode v0.81.5-dev (422da2bc0), SHA-256 ff2639739dc8b71c591cca8e02a3fb79255ef340bd7ce80bbb621ec9f9275ec8
Platform: macOS 26.6.2, Darwin 25.6.0, arm64, Apple M3 Pro

Local-build disclosure: the tested binary carries two local commits ahead of
008abc44b. Only one touches provider code, 422da2bc0, which adds a single
refresh_prompt_skills_snapshot() call in set_working_dir. It does not read,
set, or route on JCODE_NAMED_PROVIDER_PROFILE. The defect is in the
OpenAI-compatible provider path, which those commits do not modify.

Summary

With JCODE_NAMED_PROVIDER_PROFILE=<name> set, jcode run -m <model> does not
route to the named profile. It answers from the configured cloud default while
appearing to succeed.

The failure is silent. A deliberately nonexistent model id returns a confident
answer and exit code 0, and the local server records no corresponding request.

This is not a request for the environment variable to be supported. It is a
report that it is honored on some paths and ignored on this one, so a user who
sets it gets a plausible answer from the wrong model instead of an error.
Partial honoring is worse than no support, because the result is confidently
wrong rather than obviously broken.

Severity is raised by the observed consequence: this produced a false
verification claim in a downstream repository that was committed before the
routing was checked against server logs.

Reproduction

Any configured OpenAI-compatible named profile reproduces this. The profile used
here points at a local mlx-serve instance on 127.0.0.1:11234.

# ~/.jcode/config.toml
[providers.mlx-serve]
provider_type = "openai-compatible"
base_url = "http://127.0.0.1:11234/v1"
Case A — environment variable, nonexistent model (the defect)
JCODE_NAMED_PROVIDER_PROFILE=mlx-serve \
  jcode run -m "mlx-community/DOES-NOT-EXIST-9999" "Reply with exactly: ok"

Observed:

ok
[Tokens] upload: 11593 download: 5 cache_read: 0 cache_write: 0
exit=0

The model id does not exist on any server. The answer came from the cloud
default. The mlx-serve access log records no request for this call.

Case B — supported flag, identical model id (correct behavior)
jcode run --provider-profile mlx-serve \
  -m "mlx-community/DOES-NOT-EXIST-9999" "Reply with exactly: ok"

Observed:

  endpoint: http://127.0.0.1:11234/v1/chat/completions
  model: mlx-community/DOES-NOT-EXIST-9999
  auth: local endpoint (no auth)
  status: 503 Service Unavailable
exit=1

This is the desired behavior and the contrast that makes the defect clear: the
same input either fails loudly with the endpoint named, or succeeds silently
from the wrong provider, depending only on how the profile was selected.

A gibberish profile name in Case A behaves identically to a valid one, which
confirms the variable is not consulted on this path.

Root cause

JCODE_NAMED_PROVIDER_PROFILE is read across the codebase, but not once in
the OpenAI-compatible provider crates:

$ grep -rn 'JCODE_NAMED_PROVIDER_PROFILE' crates/jcode-provider-openai-runtime/ crates/jcode-provider-openai/ | wc -l
0

The Anthropic-compatible runtime implements exactly the missing behavior, in
crates/jcode-provider-anthropic-runtime/src/lib.rs:135:

fn active_anthropic_profile_models() -> Option<Vec<String>> {
    let Ok(profile_name) = std::env::var("JCODE_NAMED_PROVIDER_PROFILE") else {
        return None;
    };
    let profile = jcode_base::config::config().providers.get(&profile_name)?;
    if !matches!(
        profile.provider_type,
        jcode_base::config::NamedProviderType::AnthropicCompatible
    ) {
        return None;
    }
    // ...
}

crates/jcode-provider-openrouter-runtime/src/lib.rs:337 and
crates/jcode-base/src/provider/startup.rs also consult the variable. The
OpenAI-compatible path is the asymmetry.

Expected behavior

Either of these resolves the report; the choice is a maintainer design decision:

  1. Honor it. The OpenAI-compatible path resolves
    JCODE_NAMED_PROVIDER_PROFILE the way the Anthropic path already does, so
    both selection mechanisms agree.
  2. Reject it. If --provider-profile is intended to be the only supported
    selector for this path, then setting the variable without the flag should
    fail with a message naming the supported flag, rather than falling back.

What should not remain is the current third option, where the variable is
accepted, ignored, and answered from a different provider.

Relationship to existing issues

  • #712 (closed) is adjacent but distinct. There, auth-test actively
    cleared JCODE_NAMED_PROVIDER_PROFILE via
    force_apply_openai_compatible_profile_env, so the probe evaluated the wrong
    target. Here, run never reads the variable on the OpenAI-compatible path at
    all. The shared theme is that profile selection is not uniform across
    commands, and #712's fix did not generalize.
  • No open issue was found for this behavior. Searched 1jehuang/jcode for
    JCODE_NAMED_PROVIDER_PROFILE, run silently ignores profile, and
    provider-doctor on 2026-08-31.

Downstream mitigation already applied

Recorded here so the maintainer can see this is a report, not a support request.
The affected downstream repository has retracted the false verification claim,
documented --provider-profile as the only supported invocation, and added a
regression test asserting that an unknown local model exits nonzero. That test
was confirmed to fail when the defect is reintroduced, not merely to pass today.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the two reproduction commands and compare the local server logs. Read crates/jcode-provider-anthropic-runtime/src/lib.rs:135, then inspect the OpenAI-compatible runtime crates and crates/jcode-base/src/provider/startup.rs for profile selection. Done means the environment-variable path either routes correctly or fails explicitly, with regression coverage for an unknown model.

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
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.