Repository navigation
Description
Description
On Windows, a TUI client launched from a terminal whose CWD drive letter has non-canonical casing (e.g. c:\repo instead of C:\repo) registers a second location in the shared service whose instruction-source activation stack-overflows:
level=WARN message="failed to activate instruction source" cause="Cause([Die(RangeError: Maximum call stack size exceeded.)])"
Instruction discovery for that location is then permanently unavailable, and every prompt in it fails with:
Instructions.InitializationBlocked: Instruction initialization blocked by unavailable sources: core/instructions
at InstructionState.observe / InstructionState.prepare / SessionRunner.prepareContext / SessionRunner.drain
Root cause — ancestorDirectories in packages/core/src/config/plugin/instruction.ts (identical in v2.0.21 and v2.0.22):
function ancestorDirectories(start: string, stop: string): string[] {
if (start === stop) return [start]
return [start, ...ancestorDirectories(dirname(start), stop)]
}startcomes fromfs.resolve(location.directory)— the client's raw CWD. Bun'sfs.realPathdoes not case-canonicalize on Windows, so a lowercasec:\form survives resolution (confirmed in the logs: same-run git spawns showcwd="C:\repo"andcwd="c:\repo").stopcomes fromfs.resolve(location.project.directory), derived fromgit rev-parse --show-toplevel, which canonicalizes toC:\repo.- When the two differ only in casing,
start === stopnever matches: the walk recurses upward, reaches the drive root wheredirname("c:\") === "c:\", and self-recurses until the stack overflows. The sibling walkerFileSystem.up(packages/util/src/fs-util.ts) has a root guard (if (parent === current) break) —ancestorDirectorieslacks it. - Downstream: the dead activation marks the
instruction-discoverystateunavailable(),InstructionDiscovery.listreturns the Unavailable signal, and every session drain in that location throwsInitializationBlocked.
Suggested fix
- Add the same root guard
fs.uphas (if (dirname(start) === start) return [start]), so the walk terminates regardless. - Compare case-insensitively on
win32(or canonicalize both sides through a case-resolving path API —path.resolvealone is insufficient since Bun'srealPathpreserves drive-letter casing on Windows).
Workaround (verified): launch clients with canonically-cased CWDs (e.g. a wrapper that rewrites a leading c:\ to C:\ before exec), then restart the service to clear the poisoned location.
Plugins
One project-local plugin (unrelated — failure is in core location/instruction initialization, reproducible with the second client alone).
OpenCode version
v2.0.21 (verified the cited code is unchanged in v2.0.22)
Steps to reproduce
- On Windows, launch a first TUI from a canonically-cased CWD (
C:\repo). Prompts work normally. - Launch a second TUI from a terminal whose process CWD is the same directory with a lowercase drive letter (
c:\repo— e.g. Git Bash resolves/c/repothis way). - In the second TUI, send any prompt — the drain fails with
InitializationBlocked: core/instructions. The overflow recurs each time the lowercase location boots (42 occurrences in one day of logs on this machine).
Screenshot and/or share link
No response
Operating System
Windows 11 (10.0.26200), x64
Terminal
Windows Terminal
Activity
github-actions commentedon Oct 2, 2026
This issue might be a duplicate of existing issues. Please check: