[Bug]: Thread title and branch-name generation fail silently when the text generation provider is unhealthy
Nobody has claimed this yet.
- 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
Steps to reproduce
- Have both Codex and Claude enabled as providers. Leave Settings → Text generation model untouched, i.e. on its default (
instanceId: "codex",gpt-5.6-luna). - Make the Codex CLI unusable without disabling the provider — e.g. corrupt
~/.codex/config.tomlso the app-server refuses to load it. In my case a concurrent write left a duplicate table + an orphaned key, and the provider probe recorded:"status": "error", "message": "Codex app-server provider probe failed: failed to reload config: ~/.codex/config.toml:7:1: duplicate key." - Start a new thread with any first message.
- Observe the thread title and, for worktree threads, the generated branch name.
- Right-click the thread → Regenerate title.
Expected behavior
Either:
- text generation falls back to a provider that is actually usable (Claude was
status: "ready"and authenticated the whole time), or - the failure is surfaced the way
generateCommitMessagesurfaces it (Text generation failed in generateCommitMessage: …, see #5182) — a toast or a thread-activity entry.
Actual behavior
Nothing happens, and nothing tells you why.
- Thread titles permanently stay as the raw
titleSeed(the first message text), so the feature looks like it is simply not implemented. - Worktree branch names permanently stay as the
t3code-<hash>fallback — all 20 of my worktrees aret3code-09b397af,t3code-0a41d30a, … - Regenerate title clears the pending state and writes no title. In my event store: a
clientthread.meta-updatedwith"regenerateTitle": trueat12:24:03.721Z, then aserverthread.meta-updatedwith"titleRegeneration": nullat12:24:08.553Zand no title. No error anywhere in the UI. - Meanwhile commit-message generation through the same broken provider does show an error, so the app is inconsistent about the same underlying failure.
Two things combine to make this silent:
- No health-based fallback.
resolveTextGenerationProvider→isModelSelectionProviderEnabledonly falls back when the instance isenabled: false. An instance that is enabled but whose probe is instatus: "error"stays selected forever. (resolveSourceControlWriterModelSelectionright next to it does consultisProviderAvailable, so the helper already exists.) ThefallbackTextGenerationProviderpath also only scans the legacysettings.providersmap, which is empty on an instance-based config, so even a disabled provider would not have produced a fallback here. - The failure is swallowed. Both
maybeGenerateThreadTitleForFirstTurnandmaybeGenerateAndRenameWorktreeBranchForFirstTurnend inEffect.catchCause(cause => Effect.logWarning(...)). It never reaches the client — no toast, nothread.activity-appended.
Related, but not the same report: #5182 (closed) is the "why is Codex the default text generation provider when I don't use Codex" half of this. This issue is about what happens after that default silently stops working.
Impact
Minor bug or occasional failure
Version or commit
0.0.31
Environment
Linux (CachyOS), t3code 0.0.31 desktop, Codex CLI 0.146.0, Claude Code 2.1.221 (Claude Max), providers: codex (enabled, status: "error") + claudeAgent (enabled, status: "ready")
Logs or stack traces
# ~/.t3/caches/codex.json
{
"displayName": "Codex",
"enabled": true,
"installed": true,
"status": "error",
"message": "Codex app-server provider probe failed: failed to reload config: ~/.codex/config.toml:7:1: duplicate key.",
"checkedAt": "2026-08-04T20:47:11.045Z"
}
# ~/.t3/caches/claudeAgent.json — healthy the entire time
{
"displayName": "Claude",
"status": "ready",
"auth": { "status": "authenticated", "type": "Claude Max" },
"checkedAt": "2026-08-04T20:47:12.652Z"
}
# state.sqlite — every title write in ~3 months of history came from `client`
# (manual renames) or `provider` (the "New session - <ts>" mirror).
# Not one `server` actor title write:
sqlite> SELECT occurred_at, actor_kind, payload_json FROM orchestration_events
WHERE event_type='thread.meta-updated' AND payload_json LIKE '%title%'
ORDER BY sequence DESC LIMIT 3;
2026-07-31T12:24:08.553Z|server|{"threadId":"…","titleRegeneration":null,"updatedAt":"…"}
2026-07-31T12:24:03.721Z|client|{"threadId":"…","regenerateTitle":true,"previousTitle":"i need to update some info in stores, ignore that …","titleRegeneration":…}
2026-07-28T16:23:37.784Z|client|{"threadId":"…","title":"Pusher Security","updatedAt":"…"}
Workaround
Set Settings → Text generation model to a provider that works (Claude → Haiku 4.5). Titles and branch names start generating immediately. But you have to already suspect the setting exists — nothing in the product points you at it, because the failure is never surfaced.
Suggested fix
- Have
resolveTextGenerationProviderconsider provider availability/health, not justenabled, and makefallbackTextGenerationProviderscanproviderInstancesrather than only the legacyprovidersmap. - On title / branch-name generation failure, append a
thread.activity-appendedentry (or reuse theText generation failed in <operation>surfacing that commit-message generation already has) instead of onlyEffect.logWarning.
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
Trace resolveTextGenerationProvider, isModelSelectionProviderEnabled, and fallbackTextGenerationProvider for instance selection and health checks. Then inspect maybeGenerateThreadTitleForFirstTurn and maybeGenerateAndRenameWorktreeBranchForFirstTurn alongside generateCommitMessage and issue #5182. Done means an unhealthy selected provider falls back when possible, and title or branch-generation failures reach the user through an activity entry, toast, or equivalent error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 56/100