pingdotgg / pingdotgg/t3code

[Bug]: One-shot text generation (commit/PR/branch/title) ignores the provider's configured model and falls back to claude-haiku-4-5, which backend guardrails can block

Open
#12,651 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

accepted bug via-triage
Dominant language
TypeScript
Stars
23k
Forks
5.9k
Avg merge
11h 14m
Merged PRs (30d)
357

Description

Before submitting
  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.
Area

apps/server

Environment
  • T3 Code 0.0.42 (linux-x64 runtime at ~/.t3/runtime/versions/0.0.42)
  • Arch Linux (kernel 7.2.3-arch1-3)
  • Provider: claudeAgent instance with binaryPath pointing at a wrapper that runs the Claude CLI through OpenRouter (ANTHROPIC_BASE_URL=https://openrouter.ai/api), custom model z-ai/glm-5.3-flash
  • OpenRouter workspace guardrails block Anthropic models (only the GLM model is allowed)
Steps to reproduce
  1. Use a claudeAgent provider whose backend refuses claude-haiku-4-5 (e.g. OpenRouter with workspace guardrails that exclude Anthropic models), with a working custom model configured for threads.
  2. Leave textGenerationModelSelection unset (default settings).
  3. Press Commit on any repo with staged changes.

I captured the exact spawn t3 issues (via a logging wrapper around the configured binary):

claude-ori -p --output-format json \
  --json-schema {"type":"object","properties":{"subject":{"type":"string"},"body":{"type":"string"},"branch":{"type":"string"}},...} \
  --model claude-haiku-4-5 \
  --settings {"disableAllHooks":true} --tools '' --disable-slash-commands \
  --strict-mcp-config --permission-mode dontAsk

→ exit 1. stdout contains the real failure:

{"api_error_status":400, "is_error":true, "result":"API Error: 400 0 endpoints out of 4 requested are available matching your guardrail restrictions and data policy. … Model blocked by guardrail: 4 endpoints excluded", ...}

stderr contains only an informational line from our credential wrapper ("Using the OpenRouter credential from the global credential ~/.ori/credentials.json.").

Expected behavior

Commit-message generation should use a model that is actually configured/available on the provider instance — e.g. the instance's defaultModelSelection / custom model — instead of a hardcoded fallback slug that the backend may refuse.

Actual behavior

Every one-shot text-generation operation fails: the Commit button shows

Text generation failed in generateCommitMessage: Claude CLI command failed: Using the OpenRouter credential from the global credential ~/.ori/credentials.json.

i.e. the stderr of the spawn (the wrapper's informational notice) is shown as the entire error, while the real API error sits in stdout and is discarded. Thread-title generation fails the same way (I observed ~36 failing title spawns over several hours, 0 successes) and generateBranchName / generatePrContent share the same path.

Root cause in the 0.0.42 bundle: with settings.textGenerationModelSelection unset, resolveTextGenerationProvider()fallbackTextGenerationProvider() selects DEFAULT_TEXT_GENERATION_MODEL_BY_PROVIDER[claudeAgent] = "claude-haiku-4-5", ignoring the instance's configured default/custom model. A secondary problem is that runClaudeJson reports stderr when non-empty on non-zero exit, so any wrapper's stderr chatter masks the actual API error from stdout.

Workaround

Setting textGenerationModelSelection explicitly in ~/.t3/userdata/settings.json fixes it immediately (picked up live, no restart needed):

"textGenerationModelSelection": { "instanceId": "claudeAgent", "model": "z-ai/glm-5.3-flash" }
Suggested fixes
  1. When textGenerationModelSelection is unset, fall back to the enabled provider instance's configured default model (e.g. defaultModelSelection/custom model) rather than a hardcoded slug; at minimum, skip fallback slugs that don't resolve in the instance's model catalog.
  2. When the spawned CLI exits non-zero, include the stdout API error (or at least api_error_status/result from the JSON) in the surfaced error instead of preferring stderr, which may only contain wrapper notices.
Impact

Major degradation or frequent failure

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

Start in apps/server by tracing resolveTextGenerationProvider() and fallbackTextGenerationProvider(), then inspect runClaudeJson for non-zero exit handling. Verify that unset textGenerationModelSelection uses the enabled provider instance's configured model and that surfaced failures include the stdout API error rather than wrapper-only stderr; check commit, title, branch, and PR generation paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.