Repository navigation
Description
Summary
A scheduled task created through the Orchestrator MCP schedule_task tool that launches a fresh thread per run (bindToCurrentThread: false, or a projectId other than the caller's, which defaults to unbound) always provisions that thread's worktree from a hard-coded baseRef: "main" with startFromOrigin: true. In a Git project whose default branch is not main (for example master or trunk) and which has no main branch locally or on origin, every run creates a new top-level thread whose only run fails at workspace preparation with git worktree add failed. The scheduler records each of these runs as lastRunStatus: "succeeded", so the task stays enabled and keeps producing failed threads without any signal in the task list or to the scheduling agent.
Steps to reproduce
Known case, not executed end-to-end against a running T3 server:
- Open a Git project whose only branch is
master, with anoriginremote that also has onlymaster. - From an agent thread in that project, call
schedule_taskwith{"title":"Hourly check","prompt":"Report repository status.","schedule":{"type":"interval","everyMs":3600000},"bindToCurrentThread":false}. - Call
run_scheduled_task_nowwith the returned task id, or wait for the next interval. - Open the thread created by that run, then call
list_scheduled_tasks.
The git commands the launch path issues for step 3 were executed in a disposable repository with the same shape (bare origin containing only master, plus a clone):
$ git remote get-url origin # exit 0
$ git fetch --quiet origin '+refs/heads/main:refs/remotes/origin/main'
fatal: couldn't find remote ref refs/heads/main # exit 128; code then falls back to `git fetch origin` (exit 0)
$ git show-ref --verify --quiet refs/remotes/origin/main # exit 1, so the local baseRef "main" is used
$ git -c checkout.workers=0 worktree add -b t3code/abc123 ../wt/t3code-abc123 main
fatal: invalid reference: main # exit 128
$ git symbolic-ref refs/remotes/origin/HEAD
refs/remotes/origin/master
$ git -c checkout.workers=0 worktree add -b t3code/ok ../wt/t3code-ok master
Preparing worktree (new branch 't3code/ok') # control, exit 0A repository with only trunk and no remote fails the same worktree add ... main with fatal: invalid reference: main.
Expected behavior
The schedule_task tool description promises that an unbound task launches a working fresh thread per run: "use false only when the user wants a fresh top-level thread per run. Elsewhere each run launches a fresh thread." The tool exposes no base-branch parameter and says nothing about a main branch being required, so a fresh-thread run in a valid Git project with a different default branch should start its agent in a usable workspace.
Actual behavior
By static trace of the supported entry point: schedule_task stores { type: "worktree", baseRef: "main", startFromOrigin: true } for every unbound task, and update_scheduled_task re-applies the same value whenever bindToCurrentThread is passed. Each run calls ThreadLaunchService.launch, which returns after dispatching thread creation and forking workspace preparation into the background. Preparation finds no origin/main, keeps the literal local main, and runs git worktree add -b t3code/<id> <path> main, which fails as shown above. The thread receives a "Workspace preparation failed" item ending in git worktree add failed (stderr is dropped; see #4380). Because launch already returned, the scheduler's Effect.exit is a success, and it records lastRunStatus: "succeeded" with lastRunError: null, re-arms nextRunAt, and leaves the task enabled. The Settings badge and the list_scheduled_tasks summary both show success. Runtime reproduction through a running T3 server was not executed.
Evidence
- Expected source:
schedule_tasktool description in apps/server/src/mcp/toolkits/orchestrator/tools.ts:100. - Failure source: hard-coded strategy in apps/server/src/mcp/OrchestratorMcpService.ts:196-201 used at L1348 (create) and L1420 (update); background preparation fork in apps/server/src/orchestration-v2/ThreadLaunchService.ts:680 with the origin fallback at L333-367; scheduler status at apps/server/src/scheduledTasks/ScheduledTaskService.ts:557; the git transcript above.
- Evidence provenance: static
- Local verification: static-proof
- Reproduction completeness: complete
Runtime reproduction through T3 was not run. The static proof covers the reachable path from the MCP tool: the default at OrchestratorMcpService.ts:1322-1324 makes any other-project projectId unbound; ScheduledTaskService.upsert stores the strategy without validation; GitVcsDriverCore.fetchRemote falls back to a plain fetch on a missing remote ref; remoteBranchExists is false; and createWorktree passes the unresolved main to git worktree add. The git commands were executed directly and produced the failures shown. The Settings UI scheduling path also defaults its base to main (apps/web/src/components/settings/ScheduledTasksSettings.tsx:595) but lets the user pick another branch, so it is not a clean control. GitVcsDriverCore.resolveDefaultBranchName already exists in the server.
Restoration check
Using the reproduction above (a master-only project with a master-only origin), an unbound scheduled run currently yields a thread whose run failed at workspace preparation with git worktree add failed, while the task reports lastRunStatus: "succeeded". After the fix, the same run starts its agent in a prepared worktree (in this fixture, from master). Control: a project that does have main must still prepare its fresh-thread runs from main, and bound tasks (bindToCurrentThread: true) must keep posting into the calling thread without a worktree.
Additional context
The scheduler records whether a run was dispatched, not whether its thread was prepared, for both bound and unbound runs; no contract text defines lastRunStatus, so this report treats the misleading "succeeded" status only as a consequence that hides the failure, not as a separate defect. Workarounds available today: use bindToCurrentThread: true (runs share the calling thread's context and checkout and queue behind its activity), or edit the task in Settings, Scheduled tasks, and pick a real base branch (a later update_scheduled_task that passes bindToCurrentThread resets the base to main). A non-Git project with an unbound schedule also fails every run at the same preparation step, with "Failed to resolve the VCS driver for this Git command."; that may share the restoration but was not traced further. Related: #4380 (git stderr discarded), discussion #6866 (configurable default base branch for new worktree threads).
Area
apps/server
Impact
Major degradation or frequent failure. Every fresh-thread run of an MCP-created schedule fails in Git projects without a main branch, and the scheduler records each run as succeeded, so failed threads accumulate unnoticed.
Version or commit
main at 6f9cea00ae967f38fa3cdc9c07f92031806f4264.
Environment
Source inspection of pingdotgg/t3code main at 6f9cea0. Git behavior checked with git 2.56.0 on macOS with global and system config disabled. The T3 server itself was not run.
Workaround
Editing the task's base branch in Settings, or binding runs to the calling thread, avoids the failure today, at the cost of manual per-task setup or giving up per-run fresh threads.
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Activity
Ayushlm10 commentedon Oct 7, 2026
The same hard-coded strategy also breaks the "No project" (scratch) project. That project isn't a git repository, so creating a worktree fails no matter which base branch is used.
Repro on T3 Code Nightly 0.0.46-nightly.20261007.2761, macOS 26.4.1, with a Claude Code agent:
schedule_taskwithprojectIdset to the No project (scratch) project,bindToCurrentThread: false, and an interval schedule.run_scheduled_task_now.The run's thread fails before the agent starts:
run_scheduled_task_nowandlist_scheduled_tasksstill reportlastRunStatus: "succeeded", as this issue describes.The cause is
scheduledTaskWorkspaceStrategyinapps/server/src/mcp/OrchestratorMcpService.ts. It returns{ type: "worktree", baseRef: "main", startFromOrigin: true }for every unbound task, whatever the project is.Setting the task's Workspace to Project checkout in Settings → Scheduled tasks works around it. The next run got its own scratch folder and completed.
Resolving the workspace from the project would fix both cases. For a project that isn't a git repository, that means running in the project folder.
jlipworth commentedon Oct 9, 2026
Another case: a repo whose only remote isn't named
origin. In mine the remote isgitlab(gitlab/HEAD -> gitlab/<default>), there's nomainanywhere, and an unbound weekly task failed with the samegit worktree add failed.With #16215 as it stands, I think this repo works, but only by luck:
resolveDefaultBranchName(workspaceRoot, "origin")finds nothing, so the PR falls back to the branch currently checked out in the root. That happens to be the default branch here. If the root were sitting on a feature branch, every scheduled run would branch from that feature branch.ThreadLaunchService.ts:336turnsstartFromOriginoff when there's nooriginremote, so these runs never fetch. They start from the local branch even though the task asked to start from the remote.Possible fix: when
origindoesn't exist, use the branch's upstream remote, or the only remote if there's just one, both for finding the default branch and for the fetch.filipenevola commentedon Oct 14, 2026
Another case: a regular registered project (not Scratch) whose root is a plain folder containing several git repos as subfolders. #17451 doesn't cover this; per the triage on #18615, plain non-git project folders are out of scope there.
T3 Code Nightly 0.0.46-nightly.20261009.2873, macOS 26.6.2, Claude agent.
Setup:
workspaceRoot=<ws>/quaveone, with no.git. The repos live in<ws>/quaveone/web,<ws>/quaveone/infra, and so on.repositoryIdentity: nullanddefaultThreadEnvMode: null.fixed_timetask was created withschedule_task. It is unbound (boundThreadId: null).websubfolder withgit -C <ws>/quaveone/web worktree add …. It only needs T3 to start the thread in the project root.The 2026-10-14 08:00 UTC run failed about 30 ms after it was requested, before the agent started (
startedAt: null):list_scheduled_tasksstill showslastRunStatus: "succeeded"for the task, and nothing notified anyone. The only sign of the failure was a new thread infailedstatus. For a weekly job, that means a whole week of work gets skipped without anyone noticing.Suggested fix: when the project root isn't a git work tree, treat the strategy as
root, the same coercion #17451 does for Scratch, but based on whether the folder is a git repo rather than whether it is Scratch. This multi-repo "workspace folder" layout seems common for agents that manage their own worktrees.rdbell commentedon Oct 17, 2026
Confirmed end to end on T3 Code 0.1.0 (Linux, Claude agent), in a repo whose only branch is
master(origin/HEAD -> origin/master, nomainlocally or on origin).update_scheduled_taskwas called withbindToCurrentThread: falseand a newfixed_timeschedule. The stored workspace strategy became{"type":"worktree","baseRef":"main","startFromOrigin":true}(the update path noted in [Bug]: schedule_task gives unbound tasks baseRef "main", which breaks repos without a main branch #16577).Git command failed in GitVcsDriver.createWorktree (...): git worktree add failed, with no reason tag. Running the samegit worktree add -b <branch> <path> mainby hand givesfatal: invalid reference: main(the case fix(server): a git failure caused by a missing ref now says so #17794 tags).list_scheduled_tasksstill reportslastRunStatus: "succeeded"(fix(server): scheduled runs record the turn's real outcome #18213).A new thread started from the UI in the same project gets a worktree normally, so only the scheduled-task strategy is affected.
juliusmarminge commentedon Oct 21, 2026
Reproduced on e27a03e: a scheduled task launching a fresh thread in a repository whose default branch is
masterfailed withref_not_found. #22801 (GitCafe 22800) resolves the project's default branch instead of assumingmain; on a real server both a fresh-thread schedule and an explicit unbind completed frommaster, and an independent rebuild of the run matched. Existing saved tasks are not migrated. Desktop, mobile and other connection modes remain unverified.coygeek commentedon Oct 22, 2026
Keeping this open: both current main (
96bae546) and stable v0.1.1 still storebaseRef: "main"for fresh-thread MCP schedules, including explicit unbinding, so the original master-only case remains. #22801 addresses this but is still open and unmerged; the successful verification described above applies to that PR. #17451 is released in v0.1.1 and fixes the Scratch subcase only. This recheck was source-based, not a new live-server reproduction.thesettingsuns commentedon Oct 25, 2026
Also reproduced on Windows 11 with T3 Code 0.1.2-nightly.20261021.3499, both variants:
master(nomainlocally or on origin), projectdefaultThreadEnvMode=local: aschedule_taskwithbindToCurrentThread: falsefails before the agent starts withgit worktree add failed (ref_not_found).Failed to resolve the VCS driver for this Git command.succeeded, while the run's thread shows as failed.Workaround that works here: create the task in Settings > Scheduled tasks > New task with Workspace "Use the project checkout". Its scheduled runs start fresh threads in the project root and complete (tested on a real scheduled firing). MCP
schedule_taskcannot set this, and the Settings editor cannot turn an existing MCP-created bound task into a fresh-thread one, so such tasks had to be re-created in the UI.meded90 commentedon Oct 27, 2026
Still reproduces on T3 Code 0.1.3-nightly.20261027.3754 (macOS, Claude agent).
master(origin/masterpresent and freshly fetched, nomainlocally or on origin).boundThreadId: null,bindToCurrentThread: false) fired and failed inThreadLaunchService.prepareInBackground→GitVcsDriver.createWorktreewithgit worktree add failed (ref_not_found), before the agent started. The automatic retry about 2 minutes later failed the same way.list_scheduled_tasksstill reportslastRunStatus: "succeeded"for that task.git worktree add -b <branch> <path> origin/masterin the same repo succeeds.Workaround: launch the prompt in a new thread with
workspaceStrategy: {type: "root"}. Would be great to get #22801 merged so existing saved tasks pick up the project's default branch.ilshat-galimov commentedon Oct 30, 2026
Same here on desktop 0.1.4 with a GitLab repo whose default branch is
master(refs/remotes/origin/HEAD -> origin/master, noorigin/main). Every run of an unbound task fails with:Repro over MCP:
schedule_taskwithbindToCurrentThread=falsestores{"type":"worktree","baseRef":"main","startFromOrigin":true}.bindToCurrentThread=truestores{"type":"root"}.bindToCurrentThread=falseresets it tobaseRef: "main".schedule_taskhas no way to set the base, so binding to a thread is the only workaround. Source isscheduledTaskWorkspaceStrategyinapps/server/src/mcp/OrchestratorMcpService.ts; #22801 looks like it fixes exactly this.tgangso commentedon Oct 31, 2026
Note
🤖 Claude Opus 5.5 responding on behalf of tgangso
Still reproduces on T3 Code 0.1.6-nightly.20261030.3940 (Windows 11, desktop app, Claude agent), in a Git repo with no
mainlocally or on origin (default branchmaster).schedule_taskwithbindToCurrentThread: falsestored{"type":"worktree","baseRef":"main","startFromOrigin":true}.Workspace preparation failed during provision worktree: Git command failed in GitVcsDriver.createWorktree.createBranch: git worktree add failed (ref_not_found)list_scheduled_tasksstill reportedlastRunStatus: "succeeded".Workaround, as noted above: give the task the project checkout workspace (
{"type":"root"}), for example in Settings > Scheduled tasks. Laterschedule_taskedits that don't passbindToCurrentThreadkeep it; passingbindToCurrentThread: falseresets it tobaseRef: "main".jlipworth commentedon Oct 31, 2026
Still reproduces on 0.1.6-nightly.20261031.3956 (macOS, desktop app, Codex agent). It's the same repo as my earlier comment: the only remote is
gitlab, the default branch isk8s_deployment, and there's nomainanywhere.Two unbound one-shot tasks failed today, each about 50 ms after the run was requested and before any provider turn:
Both tasks still have
{"type":"worktree","baseRef":"main","startFromOrigin":true}saved. Their prompts say "use the existing project checkout; do not create a worktree", but that can't help because the run fails before the agent starts.Something for #22801: it says existing tasks keep their saved strategy. Anyone who already has broken tasks will still need to re-save each one after it ships. A one-time migration, or a clear error that points at the setting, would help those users. I have 7 tasks waiting to fail the same way.
Related but separate: editing a task with
schedule_taskkeeps its storedmodelSelection. One task was created from a thread set toserviceTier: ultrafast. Its prompt was later edited to switch todefault, but the saved setting stayed on ultrafast, and the MCP tool has no field to change it.Investigated with Claude Opus 5.5 (Claude Code) via T3 Code triage.
willtraweek commentedon Nov 1, 2026
Note
🤖 Claude Opus 5.5 responding on behalf of willtraweek
Still reproduces on stable v0.1.6 (macOS 27.2 arm64, desktop app, Claude agent) in a repo whose default branch is
dev. #27983 should fix new tasks once it ships. Tasks already saved withmainwill keep failing after the upgrade, though. The fix picks the base only when a task is created, or when an update passesbindToCurrentThread, and nothing migrates stored tasks.origin/HEAD -> origin/dev. It usesmasterinstead ofmain, so there's nomainlocally or on origin.schedule_taskandbindToCurrentThread: falsewere all saved with{"type":"worktree","baseRef":"main","startFromOrigin":true}.list_scheduled_tasksstill reportedlastRunStatus: "succeeded"([Bug]: A scheduled run that fails is recorded as succeeded #17889):dev,run_scheduled_task_nowcreated the worktree and the agent started.Suggestion, untested: a one-time migration that re-resolves
baseReffor unbound tasks whose saved base doesn't exist would let upgraded installs recover without re-saving each task.Thanasis-Tsiatouras commentedon Nov 2, 2026
Additional runtime confirmation of the ordinary non-Git project case on T3 Code 0.1.7-nightly.20261101.4035.
Environment: Linux x64 server (kernel 6.8.0-138-generic, Node v26.12.1), accessed from the macOS Desktop app of the same version. The user confirmed the error came from the Linux thread viewed on macOS.
A registered project is a plain workspace folder with Git checkouts below it. The project root has no .git; git -C rev-parse --show-toplevel exits 128 with “not a git repository”.
The affected interval task is enabled, runs every 7,200,000 ms, and has:
thread_id: null
workspace_strategy_json: {"type":"worktree","baseRef":"main","startFromOrigin":true}
At 2026-11-02T13:18:59Z the live server trace records:
VcsDriverRegistry.resolve: No supported VCS repository was detected at .
GitWorkflowService.resolveWorktreeBaseRemote: Failed to resolve the VCS driver for this Git command.
ThreadLaunchService.prepareInBackground: failed during provision-worktree.
The scheduler nevertheless stores last_run_status="succeeded", last_run_error=null and schedules the next run. This is a workspace preparation failure before the agent starts.
Source at the installed commit 80120b1:
The same Scratch-only guard remains in current main as inspected on 2026-11-02. No confirmed newer-release fix was found for this subcase.
Repro: register a plain folder containing child Git checkouts; create an unbound interval schedule through MCP; let it fire. Preparation targets the plain parent folder and fails.
Verified workaround: set the existing task workspace strategy to {"type":"root"}, while keeping thread_id=null so runs still create fresh threads. The installed Settings > Scheduled tasks UI exposes this as Workspace > "Use the project checkout".
With the user's approval, I changed only workspace_strategy_json on the affected task, retained a private local rollback record, and refreshed the task through the supported schedule_task tool. No service restart or source patch was needed. After checking the memory gate and absence of another active ops-check, I manually ran the same task. The new run passed workspace preparation, acquired a provider startedAt timestamp, reached running status, and emitted assistant progress while executing its checks. This confirms the provisioning failure is resolved; the full operational check was still running when this evidence was collected.
The interval task remains enabled with a two-hour schedule, no bound thread, and its original prompt/model selection. Avoid passing bindToCurrentThread:false in a later MCP edit, because that recomputes the worktree strategy.
This matches #16183 and the non-Git case closed as duplicate in #18615. No new issue is needed.
Prepared by Codex (gpt-6.1-sol) in T3 Code triage; posted with the user’s approval.
benjamin-di commentedon Nov 8, 2026
Confirmed again for an ordinary registered non-Git project folder, distinct from managed Scratch. An actual fixed-time scheduled run failed before the provider started. The installed CLI reports
t3 v0.1.6on Linux; I separately checked the relevant source on current upstreammainat1d78b3320328709d266ffd36af0dd75e614d14de.The project root is a parent folder containing Git checkouts.
git -C <workspace> rev-parse --show-toplevelexits 128 with “not a git repository”. The unbound task has this persisted strategy:{"type":"worktree","baseRef":"main","startFromOrigin":true}The failed run records
startedAt: nulland this error:Read-only inspection of the run and task records confirms the mismatch: the run is
failed, while the task recordslast_run_status: "succeeded",last_run_error: null, andrun_count: 1. The provider never started. Failure reporting is separately tracked in #17889.Minimal reproduction shape:
schedule_taskin that project withbindToCurrentThread: false.Current-source confirmation:
scheduledTaskWorkspaceStrategystill selects a worktree for every unbound task. The default-branch resolver is present, so resolvingmainversus another branch does not address this non-Git case.ThreadLaunchServicenormalizes worktree requests for managed Scratch only.ScheduledTaskServicederives task success from dispatch acceptance.This supports the non-Git subcase already tracked here and the scope of #18583; it is not a request to change the intended fresh-worktree behavior for Git projects. I did not run current
mainor #18583 end-to-end, test other clients, or apply the project-checkout workaround during this investigation.alnimra commentedon Nov 9, 2026
Still reproduces on T3 Code server
0.1.8-nightly.20261106.4262(Linux), for a project whose folder isn't a git repository. This build already resolves the default branch, but that doesn't help this case.Steps:
.git), withdefaultThreadEnvMode: local.schedule_taskwithbindToCurrentThread: falseand a schedule a minute from now.Actual: the run's new thread fails within a second, before the agent starts:
The thread shows
lastErrorCode: workspace_preparation_failedandlatestRunStartedAt: null.list_scheduled_tasksstill showslastRunStatus: "succeeded"andlastRunError: null, which is the #17889 half.Expected: the run starts in the project root, or
schedule_taskrefuses the task when it's saved.In this build's bundled server,
OrchestratorMcpService.scheduledTaskWorkspaceStrategyreturns{type: "root"}only for bound tasks. Every unbound task gets{type: "worktree", baseRef: <resolved>, startFromOrigin: true}, without checking whether the root is a git repository or readingdefaultThreadEnvMode.ScheduledTaskService.runTasksetslastRunStatusfrom thethreadLaunch.launchexit, and the launch returns before workspace preparation fails.Between 29 Oct and 9 Nov 2026 this lost 13 runs of unbound tasks in one non-git project, including a daily task that failed every day. All 13 showed
succeeded.alexlwn123 commentedon Nov 11, 2026
Workaround for tasks already saved with
baseRef: "main", since #27983 doesn't update saved tasks: create a localmainthat tracks the default branch.At launch, a bare
mainresolves through that branch's upstream, so the run fetchesorigin/masterand starts its worktree there. It fixed a webhook-triggered task for me on 0.1.4-nightly.20261027.3770 (#26260, closed as a duplicate of this one) without re-saving it. It covers every saved task in the repo at once, and runs still get a fresh worktree. Delete the branch once your tasks are re-saved on a build with #27983.