[BUG] Team leader crashes with "getAppState is not a function" when teammate requests tool permission
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
Workflow Context
My primary use of agent teams is talking directly with individual teammates — treating each teammate as its own full Claude Code session, as the docs describe ("Each teammate is a full, independent Claude Code session"). I want to be able to direct a teammate, converse with it, paste things into it, hand it nuanced context, and let it ask me for permission when it needs to. That direct teammate-as-collaborator workflow is the main value I get out of teams vs. plain subagents. This bug blocks that workflow end-to-end, because the teammate can't run any permission-gated tool without crashing the lead.
What's Wrong?
This has happened to me twice today (2026-04-17), so it's reproducible rather than a one-off.
When a teammate (spawned via TeamCreate + Agent with team_name) requests permission for a tool use, the team leader's UI crashes with an unhandled error instead of showing the permission prompt.
The teammate's side shows the expected "Waiting for team lead approval" panel, but on the team-leader side the error below is thrown when attempting to render the permission request. The team leader never sees the approval prompt, so the teammate is blocked indefinitely.
Teammate UI (as seen):
Update(~/.claude/agents/companion.md)
⎿ Waiting for permission…
╭───────────────────────────────────────────────────────╮
│ ✻ Waiting for team lead approval │
│ │
│ ⏺ @companion-v2 │
│ │
│ Tool: Edit │
│ Action: A tool for editing files │
│ │
│ Permission request sent to team "weave" leader │
╰───────────────────────────────────────────────────────╯
What Should Happen?
The team leader should see the teammate's tool-use permission request and be able to approve or deny it.
Error Messages/Logs
Stack trace:
ERROR H.toolUseContext.getAppState is not a function. (In 'H.toolUseContext.getAppState()',
'H.toolUseContext.getAppState' is undefined)
/$bunfs/root/src/entrypoints/cli.js:8231:15642
- <anonymous> (/$bunfs/root/src/entrypoints/cli.js:8231:15642)
- qX (/$bunfs/root/src/entrypoints/cli.js:477:63169)
- sPH (/$bunfs/root/src/entrypoints/cli.js:477:76220)
- ov (/$bunfs/root/src/entrypoints/cli.js:477:76101)
- sPH (/$bunfs/root/src/entrypoints/cli.js:477:76199)
- ov (/$bunfs/root/src/entrypoints/cli.js:477:76101)
- sPH (/$bunfs/root/src/entrypoints/cli.js:477:76199)
- ov (/$bunfs/root/src/entrypoints/cli.js:477:76101)
- sPH (/$bunfs/root/src/entrypoints/cli.js:477:76199)
- ov (/$bunfs/root/src/entrypoints/cli.js:477:76101)
<details>
<summary>Full raw terminal output (including minified source context around line 8231)</summary>
ERROR H.toolUseContext.getAppState is not a function. (In 'H.toolUseContext.getAppState()',
'H.toolUseContext.getAppState' is undefined)
/$bunfs/root/src/entrypoints/cli.js:8231:15642
8228: ${w.map((uH)=>{let yH=TH[uH.question];if(yH)return`- "${uH.question}"
8229: Answer: ${yH}`;return`- "${uH.question}"
8230: (No answer provided)`}).join(`
8231 `)}`;if(G)Q("tengu_ask_user_question_finish_plan_interview",{source:G,questionCount:w.length,isInPlanMode:n,inter
: viewPhaseEnabled:n&&cY()});let oH=await xf8(g,i);K(),q.onReject(P_,oH&&oH.length>0?oH:void
0)},_[44]=g,_[45]=TH,_[46]=i,_[47]=n,_[48]=G,_[49]=K,_[50]=w,_[51]=q,_[52]=vH;else vH=_[52];let
GH=vH,NH;if(_[53]!==g||_[54]!==i||_[55]!==n||_[56]!==G||_[57]!==K||_[58]!==YH||_[59]!==w||_[60]!==q)NH=async(D_)=>
{if(G)Q("tengu_ask_user_question_accepted",{source:G,questionCount:w.length,answerCount:Object.keys(D_).length,isI
nPlanMode:n,interviewPhaseEnabled:n&&cY()});let P_={};for(let yH of w){let
eH=D_[yH.question],V_=YH[yH.question]?.textInputValue,QH=(eH?yH.options.find((v_)=>v_.label===eH):void
0)?.preview;if(QH||V_?.trim())P_[yH.question]={...QH&&{preview:QH},...V_?.trim()&&{notes:V_.trim()}}}let
oH={...q.input,answers:D_,...Object.keys(P_).length>0&&{annotations:P_}},uH=await
xf8(g,i);K(),q.onAllow(oH,[],void 0,uH&&uH.length>0?uH:void
0)},_[53]=g,_[54]=i,_[55]=n,_[56]=G,_[57]=K,_[58]=YH,_[59]=w,_[60]=q,_[61]=NH;else NH=_[61];let
hH=NH,lH;if(_[62]!==TH||_[63]!==v||_[64]!==w.length||_[65]!==_H||_[66]!==hH)lH=(D_,P_,oH,uH)=>{let yH=uH===void
0?!0:uH,eH,V_=Array.isArray(P_);if(V_)eH=P_.join(", ");else
if(oH)eH=Object.values(v[D_]??{}).filter(bI5).length>0?`${oH} (Image attached)`:oH;else
if(P_==="__other__")eH=Object.values(v[D_]??{}).filter(CI5).length>0?"(Image attached)":P_;else eH=P_;let
bH=w.length===1;if(!V_&&bH&&yH){let QH={...TH,[D_]:eH};hH(QH).catch(zH);return}_H(D_,eH,yH)},_[62]=TH,_[63]=v,_[64
]=w.length,_[65]=_H,_[66]=hH,_[67]=lH;else lH=_[67];let X_=lH,W_;if(_[68]!==TH||_[69]!==ZH||_[70]!==hH)W_=function
(P_){if(P_==="cancel"){ZH();return}if(P_==="submit")hH(TH).catch(zH)},_[68]=TH,_[69]=ZH,_[70]=hH,_[71]=W_;else
W_=_[71];let SH=W_,gH=JH?(w?.length||1)-1:w?.length||0,tH;if(_[72]!==r||_[73]!==HH)tH=()=>{if(r>0)HH()},_[72]=r,_[
73]=HH,_[74]=tH;else tH=_[74];let
y_=tH,T_;if(_[75]!==r||_[76]!==gH||_[77]!==wH)T_=()=>{if(r<gH)wH()},_[75]=r,_[76]=gH,_[77]=wH,_[78]=T_;else
T_=_[78];let
h_=T_,rH;if(_[79]!==h_||_[80]!==y_)rH={"tabs:previous":y_,"tabs:next":h_},_[79]=h_,_[80]=y_,_[81]=rH;else
rH=_[81];let M_=!(AH&&!KH),UH;if(_[82]!==M_)UH={context:"Tabs",isActive:M_},_[82]=M_,_[83]=UH;else
UH=_[83];if(C8(rH,UH),t){let D_;if(_[84]!==t.question||_[85]!==u)D_=(yH,eH,V_,bH,QH)=>u(t.question,yH,eH,V_,bH,QH)
,_[84]=t.question,_[85]=u,_[86]=D_;else D_=_[86];let
P_;if(_[87]!==t.question||_[88]!==v)P_=v[t.question]??{},_[87]=t.question,_[88]=v,_[89]=P_;else P_=_[89];let
oH;if(_[90]!==t.question)oH=(yH)=>p(t.question,yH),_[90]=t.question,_[91]=oH;else oH=_[91];let
uH;if(_[92]!==TH||_[93]!==t||_[94]!==r||_[95]!==R||_[96]!==W||_[97]!==ZH||_[98]!==GH||_[99]!==X_||_[100]!==LH||_[1
01]!==h_||_[102]!==y_||_[103]!==JH||_[104]!==wH||_[105]!==OH||_[106]!==YH||_[107]!==w||_[108]!==o||_[109]!==D_||_[
110]!==P_||_[111]!==oH||_[112]!==a)uH=EP.default.createElement(EP.default.Fragment,null,EP.default.createElement(h
Q7,{question:t,questions:w,currentQuestionIndex:r,answers:TH,questionStates:YH,hideSubmitTab:JH,minContentHeight:R
,minContentWidth:W,planFilePath:OH,onUpdateQuestionState:a,onAnswer:X_,onTextInputFocus:o,onCancel:ZH,onSubmit:wH,
onTabPrev:y_,onTabNext:h_,onRespondToClaude:LH,onFinishPlanInterview:GH,onImagePaste:D_,pastedContents:P_,onRemove
Image:oH})),_[92]=TH,_[93]=t,_[94]=r,_[95]=R,_[96]=W,_[97]=ZH,_[98]=GH,_[99]=X_,_[100]=LH,_[101]=h_,_[102]=y_,_[10
3]=JH,_[104]=wH,_[105]=OH,_[106]=YH,_[107]=w,_[108]=o,_[109]=D_,_[110]=P_,_[111]=oH,_[112]=a,_[113]=uH;else
uH=_[113];return uH}if(KH){let
D_;if(_[114]!==jH||_[115]!==TH||_[116]!==r||_[117]!==R||_[118]!==SH||_[119]!==w||_[120]!==q.permissionResult)D_=EP
.default.createElement(EP.default.Fragment,null,EP.default.createElement(SQ7,{questions:w,currentQuestionIndex:r,a
nswers:TH,allQuestionsAnswered:jH,permissionResult:q.permissionResult,minContentHeight:R,onFinalResponse:SH})),_[1
14]=jH,_[115]=TH,_[116]=r,_[117]=R,_[118]=SH,_[119]=w,_[120]=q.permissionResult,_[121]=D_;else D_=_[121];return
D_}return null}function CI5(H){return H.type==="image"}function bI5(H){return H.type==="image"}function
II5(H){return H.toolPermissionContext.mode}function xI5(H){return H.type==="image"}function uI5(H){return
Object.values(H)}function mI5(H){return H.preview}async function xf8(H,_){if(H.length===0)return;return
Promise.all(H.map(async(q)=>{let{block:K}=await ON({data:q.content,mediaType:q.mediaType,limits:_});return
K}))}var G_6,EP,IQ7=12,VI5=40,SI5=15;var uQ7=Z(()=>{fy();TN();b9();oK();BH();m8();E_();V8();$i_();BfH();WI();qmH()
;d_();L9_();bk();d1H();rj();NQ7();EQ7();bQ7();G_6=x(iH(),1),EP=x(MH(),1)});function
mQ7(H){for(let{pattern:_,warning:q}of pI5)if(_.test(H))return q;return null}var pI5;
[... extensive minified source continues — omitted for brevity; the full dump spans the entire bundle chunk containing the `By` hook shown below ...]
function a0(H){Q("tengu_unary_event",{event:H.event,completion_type:H.completion_type,language_name:await H.metada
ta.language_name,message_id:H.metadata.message_id,platform:M8.platform,...H.metadata.hasFeedback!==void
0&&{hasFeedback:H.metadata.hasFeedback}})}var AmH=Z(()=>{E_()});function By(H,_){let
q=x8(),K=k_6.useRef(null);k_6.useEffect(()=>{if(K.current===H.toolUseID)return;K.current=H.toolUseID,q((T)=>({...T
,attribution:{...T.attribution,permissionPromptCount:T.attribution.permissionPromptCount+1}}));let
O=H.toolUseContext.getAppState().toolPermissionContext.mode;Q("tengu_tool_use_show_permission_request",{messageID:
H.assistantMessage.message.id,toolName:J7(H.tool.name),isMcp:H.tool.isMcp??!1,decisionReasonType:H.permissionResul
t.decisionReason?.type,sandboxEnabled:G8.isSandboxingEnabled(),permissionMode:O}),a0({completion_type:_.completion
_type,event:"response",metadata:{language_name:_.language_name,message_id:H.assistantMessage.message.id,platform:M
8.platform}})},[H,_,q])}
- <anonymous> (/$bunfs/root/src/entrypoints/cli.js:8231:15642)
- qX (/$bunfs/root/src/entrypoints/cli.js:477:63169)
- sPH (/$bunfs/root/src/entrypoints/cli.js:477:76220)
- ov (/$bunfs/root/src/entrypoints/cli.js:477:76101)
- sPH (/$bunfs/root/src/entrypoints/cli.js:477:76199)
- ov (/$bunfs/root/src/entrypoints/cli.js:477:76101)
- sPH (/$bunfs/root/src/entrypoints/cli.js:477:76199)
- ov (/$bunfs/root/src/entrypoints/cli.js:477:76101)
- sPH (/$bunfs/root/src/entrypoints/cli.js:477:76199)
- ov (/$bunfs/root/src/entrypoints/cli.js:477:76101)
</details>
Tracing the minified source at cli.js:8231, the crash is in the By hook — the one that fires the tengu_tool_use_show_permission_request telemetry event when a permission prompt is rendered:
function By(H, _) {
let q = x8(), K = k_6.useRef(null);
k_6.useEffect(() => {
if (K.current === H.toolUseID) return;
K.current = H.toolUseID;
q((T) => ({ ...T, attribution: { ...T.attribution,
permissionPromptCount: T.attribution.permissionPromptCount + 1 } }));
let O = H.toolUseContext.getAppState().toolPermissionContext.mode; // ← throws here
Q("tengu_tool_use_show_permission_request", { ... permissionMode: O });
...
}, [H, _, q]);
}
So H.toolUseContext is present but getAppState is undefined on it. Likely cause (guess): when the permission request is forwarded from a teammate to the team leader across the team IPC boundary, toolUseContext is reconstructed from a serialized form that drops method references — so getAppState, which was a closure on the teammate process, doesn't survive the trip to the team-leader side.
Steps to Reproduce
- In Claude Code, call
TeamCreateto create a team (I usedweave). - Call
Agentwith thatteam_nameset and anameto spawn a teammate (mine:@companion-v2). - Ask the teammate to use a tool that requires permission — something not pre-approved. In my case:
Edit ~/.claude/agents/companion.md. - On the teammate side, the "Waiting for team lead approval" panel appears (shown above).
- On the team-leader side, the error above is thrown instead of the approval prompt. The teammate is stuck waiting forever.
Workaround: toggle ⏵⏵ bypass permissions mode on the team leader so permission prompts are skipped entirely — but that defeats the purpose of team-level permission gating.
Claude Model
Opus 4.7
Is this a regression?
I don't know
Claude Code Version
2.1.112 (Claude Code)
Platform
Anthropic API
Operating System
macOS (Darwin 25.2.0)
Terminal/Shell
iTerm2 (inside tmux)
Additional Information
This may be tmux-specific — please investigate that angle first. I am running Claude Code inside tmux (on iTerm2), and teams in Claude Code use tmux panes to host teammates. Prior team bugs have turned out to be tmux-specific (e.g. #23527, which hit only when pane-base-index was non-zero; and #24694, which involves the teammate/leader rendering split across tmux panes). It would not surprise me if the toolUseContext being passed to the team leader's By hook is being marshaled across a tmux pane / IPC boundary and losing its getAppState method in the process. If you cannot reproduce outside tmux, that would be a strong signal the bug lives in the tmux-pane-routing path rather than the general team permission flow.
Related existing issues (touch similar flows but none match this exact error):
- #23527 — Teammate mode fails to deliver instructions when tmux pane-base-index is non-zero (tmux-specific)
- #24694 — AskUserQuestion tool rendering in teammate pane with no leader notification (tmux teammates)
- #25254 — Team agents' messages not delivered to team lead in VS Code extension; permission prompts invisible
- #29293 — Agent Teams: Teammates fail to spawn
- #30012 — Remote Control does not show permission prompts from agent team sub-panes
16 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Team leader crashing with "getAppState is not a function" when a teammate requests tool permission — twice in one day, so reproducible — is a multi-agent session state management bug where the permission request renderer assumes application state that is not present in the team leader's current context.
From an agent team identity and authorization perspective, this crash completely breaks the team authorization model: the teammate correctly enters the "waiting for team lead approval" state, but the team leader never sees the approval prompt because the renderer crashes. The teammate is blocked indefinitely with no path to recovery.
The
getAppState is not a functionerror pattern suggests the permission request UI is attempting to access global application state that either:The fix direction: The permission request renderer must be defensive about the application state it accesses. If
getAppStateis not available (or throws), the renderer should fall back to a simpler approval UI that does not depend on the full app state.Workaround while fix is pending: After the team leader crash, kill the team leader process and restart. The teammate's pending permission request will timeout or error, but at least the team leader is functional again. Starting the team from scratch is currently the only recovery path.
For the bug report: The teammate's exact permission request (what tool, what file/action) at the time of crash would help narrow down whether this is specific to certain tool types or universal.
Exact same symptoms here! Occurred twice in less than 2 hours.
Claude Model
Opus 4.7
Is this a regression?
I don't know
Claude Code Version
2.1.112 (Claude Code)
Platform
Anthropic API
Operating System
macOS (Darwin Kernel Version 25.4.0: Thu Mar 19 19:32:59 PDT 2026; root:xnu-12377.101.15~1/RELEASE_ARM64_T8122 arm64 arm Darwin)
Terminal/Shell
iTerm2
Output
<details>
<summary>Raw output on team lead session when it occurs</summary>
</details>
Just occurred with team lead on Opus 4.6 FYI
Just happened to me. Sonnet 4.5 team lead. Claude Code v2.1.112.
Here's some of the error output, couldn't capture the whole thing very easily from Tmux:
The team member command that triggered it:
Happened to me too:
Reproduceable: every sub agent permission request triggers it. Team lead completely crashes and I have to restart the claude docker container.
Model: Sonnet 4.6 (team lead and agent)
OS: Ubuntu 24 LTS
Version: Claude Code 2.1.112 AND 2.1.111
Using tmux so difficult to capture much detail.
Error message:
Reverting to 2.1.111 until fixed
Edit also present in 2.1.111
More debugging:
cd (another repo path on the same filesystem) && git branch -a, crash.Used Claude Code to investigate Claude Code crash, of course 😆. Went a number of rounds, trying to track this down and confirm what was going on, checked it over, as far as I can tell the following is accurate:
Agent Teams Permission Dialog Crash - Bug Report
Environment:
Issue: Permission dialogs for spawned agents crash with
H.toolUseContext.getAppState is not a function---
Summary
When a spawned agent requests permission for a Bash command not on the allowlist, the permission dialog appears in the user's UI but immediately crashes with a JavaScript error. This prevents any agent team workflows that require user approval of commands.
Error:
H.toolUseContext.getAppState is not a function. (In 'H.toolUseContext.getAppState()', 'H.toolUseContext.getAppState' is undefined)---
Reproduction Steps
Minimal Test Case
H.toolUseContext.getAppState is not a function---
What We Tested
1. Team Lifecycle ✅
2. Agent Spawning ✅
Successfully spawned multiple agent types:
All agents spawned successfully with processes running and tmux panes created.
3. Agent Execution ✅
Agents execute tasks correctly:
4. Message Delivery ✅ (Post-Restart)
After a full CLI restart (exit and
--resume):<teammate-message>tags5. Permission Requests for Team-Lead ✅
When team-lead (main session) requests Bash permission:
6. Permission Requests for Spawned Agents ❌
When spawned agent requests Bash permission:
---
Detailed Crash Information
Agent Side (Agent's tmux window)
Agent correctly:
Team-Lead Side (User's main window)
Dialog appears correctly but crashes immediately.
Full Error Trace
Error Location:
/$bunfs/root/src/entrypoints/cli.js:8233:15642toolUseContextobject exists butgetAppStatemethod is undefined---
Key Findings
What Works ✅
What's Broken ❌
Spawned agent → user permission dialog interaction crashes
The bug is NOT:
The bug IS:
toolUseContext.getAppStatemethod missing---
Root Cause
THE BUG: Permission dialog interaction for spawned agents crashes with
H.toolUseContext.getAppState is not a functionThe Flow:
Why Some Commands "Worked":
Commands on the permission allowlist (git, cd, ls, grep, etc.) execute without prompting. The crash only occurs when:
toolUseContext.getAppState()Example allowlist patterns (from
~/.claude/settings.json):Impact:
---
Environment Details
CLAUDECODE=1CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1CLAUDE_CODE_USE_BEDROCK=1Agent Spawn Command Pattern:
---
Workaround (Temporary)
Until fixed, agents can only use:
To expand allowlist, add patterns to
~/.claude/settings.json:But this only helps if you know which commands the agent will need in advance.
---
Session Restart Observations
We observed that a full CLI restart (exit and
--resume) improved message delivery:Before restart:
~/.claude/teams/*/inboxes/team-lead.json)After restart:
<teammate-message>tagsNote: Restart improved message routing but did NOT fix the core permission dialog crash bug.
---
Reproducible Test Case
Simplest reproduction:
Important: Use a destructive command like
rm -rfto reliably reproduce. Commands likesleepmay be auto-approved by internal heuristics.Command Behavior Patterns
Commands that trigger permission dialog → crash:
rm/rm -rf(destructive file operations)mvon existing filesCommands that may auto-approve (no crash):
sleep- benign utility commanddate- read-only system infowhoami- read-only user infoCommands typically on allowlist (no prompt needed):
git *cd *ls *grep *make *Key Finding: Claude Code has built-in read-only command recognition. Commands like
ls,cat,head,tail,grep,find,wc,diff,stat,du,cd, and read-onlygitoperations run without prompts in every mode. This built-in list is not configurable. Commands likesleepmay also be treated as benign and auto-approved, while destructive commands likerm -rfalways require explicit permission unless pre-approved via allowlist. Only destructive commands reliably trigger the permission dialog, and therefore the crash.Verified Test Results (2026-04-17)
Test 1: Team-Lead Permission Dialogs ✅
touch /tmp/test-file-12345andrm -rf /tmp/test-file-12345Test 2: Spawned Agent Permission Dialog ❌
rm -rf /tmp/test-file-12345H.toolUseContext.getAppState is not a functionObservation: The same command (
rm -rf) triggers functional permission dialogs for team-lead but crashes when requested by spawned agents. The bug appears to be in the permission dialog code path used when spawned agents request permission, not in command classification or allowlist logic.UI Difference Between Team-Lead and Agent Dialogs
Team-Lead Permission Dialog (Working):
Spawned Agent Permission Dialog (Crashes):
Observed Difference: Agent dialogs include agent name in header ("· @test-agent"), while team-lead dialogs do not.
Hypothesis: The agent-attributed dialog may follow a different UI code path that attempts to call
H.toolUseContext.getAppState(). The error occurs at line 8233:15642 in the bundled CLI. Team-lead dialogs work correctly, possibly because they don't trigger this code path.Note: Without access to the harness source code, we cannot definitively determine whether the agent attribution is the actual cause or merely correlated with the crash.
---
Permission Configuration Hierarchy
Claude Code follows a tiered settings precedence (highest to lowest priority):
Settings Precedence
.claude/settings.local.json).claude/settings.json)~/.claude/settings.json)Common Settings File Locations
Global User Settings:
~/.claude/settings.json- applies to all sessionsProjects Directory Settings:
<projects-dir>/.claude/settings.json- applies to all repos under that directoryRepository-Specific Settings:
<repo>/.claude/settings.json- applies only within that repoLocal Project Settings (gitignored):
<repo>/.claude/settings.local.json- per-developer overrides, not checked inMerge Behavior
Deny rules take precedence: If a tool is denied at ANY level, no other level can allow it.
Allow rules are additive: Allow rules from multiple levels are combined. A command matching an allow pattern at ANY applicable level will be auto-approved (unless blocked by a deny rule).
Evaluation order: deny → ask → allow. The first matching rule wins within each level, then precedence rules determine which level takes priority.
Reference: See https://code.claude.com/docs/en/permissions for complete permission system documentation.
Example Allowlist Entries
Typical global settings might include broad patterns:
While project-specific settings might be more conservative:
Commands like
rm,sleep,date,whoamiare typically NOT on allowlists, triggering either:---
Expected Behavior
Actual Behavior
toolUseContext.getAppState is not a function---
Related Information
This may be related to GitHub issue #49865 (user-reported crashes with agent teams).
The
toolUseContextobject appears to be missing thegetAppStatemethod specifically in the context of spawned agents. The same permission flow works correctly for the parent/team-lead session, suggesting the context is initialized differently for spawned agents.The error occurs in the permission explainer flow (around line 8233 in the bundled CLI), likely when trying to determine application state for the permission decision.
---
---
Notes on Agent Teams Feature
Agent teams is a research preview feature that requires
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1. The CHANGELOG shows a history of agent team bugs related to message passing, permission handling, and environment propagation across versions. This permission dialog crash appears to be a new issue not yet addressed in recent releases.Claude Code is closed-source, so the exact cause of the
toolUseContext.getAppStateerror cannot be determined without access to the harness code.---
---
Report Attribution
Primary Testing and Observation: Colin Leong
Documentation and Analysis: Claude Sonnet 4.5
Collaboration: This report is a joint effort combining hands-on testing (Leong) with systematic documentation and analysis (Sonnet 4.5). User feedback shaped the testing approach and ensured accuracy of observations vs. hypotheses.
---
Report Date: 2026-04-17
Claude Code Version: 2.1.112
Issue Severity: Critical (blocks all agent team workflows requiring Bash approval)
Environment: Linux, AWS Bedrock backend
Hmmm, just tried it in 2.1.111 and still had the bug. Fresh tmux session and everything. Checked claude --version, updated the symlink to point to the .111, checked /stats inside claude.... same bug
Ah maybe not, autoupdated keeps changing me to 2.112.
Edit: disabled autoupdate, checked claude --version, had team lead also run claude --version, no more 2.1.112, but same bug
OK, version 2.1.110 works.
Version Testing Update
I tested across three versions to identify when this regression was introduced:
| Version | Status | Notes |
|---------|--------|-------|
| 2.1.110 | ✅ Works | Permission dialog functions correctly, no crash |
| 2.1.111 | ❌ Broken | Permission dialog crashes immediately |
| 2.1.112 | ❌ Broken | Same crash as 2.1.111 |
Conclusion: This is a regression introduced in v2.1.111. The functionality worked correctly in 2.1.110.
Testing note: I had to disable autoupdate in
~/.claude/settings.jsonto test older versions:This narrows the scope for investigation - the bug was introduced in changes between 2.1.110 and 2.1.111, specifically in the spawned agent permission dialog code path.
How to Downgrade to Claude Code v2.1.110
Quick Guide
1. Disable Auto-Update
Edit
~/.claude/settings.jsonand add:2. Symlink to v2.1.110
3. Verify Version
Reverting to Latest
To go back to the latest version:
Notes
~/.claude/versions/directory contains all downloaded Claude Code versionsRan into the same issue with tmux managed experimental agent teams. Same outcome - parent team crashes with "not a function" error.
@cleong110 Just adding that on macOS my symlink was in ~/.local/bin/claude, I didn't have version 2.1.110 downloaded locally, so I ran
which claudeto see where it was pointing:I ran
rm ~/.local/bin/claude, then I ran the official installation script, but with the-s 2.1.110argument, like this:For some reason, when I ran the script this way I was getting the error:
So I decided to add a sudo to the command, like this:
And it was done
Ah, and to get Opus 4.7 working on this version, I used the command
/model opus-4-7[1m]Confirming the same issue on 2.1.112, macOS, in the team-lead-managing-teammates workflow (spawning teammates via
Agentwithteam_nameset; team lead routes their work and approves tool use). Same underlying bug as @jonleung's direct-teammate-conversation workflow; different user-facing flow, same crash signature.Three crashes in one real working session today. Trigger each time was identical: a spawned teammate needed permission to use a tool the team-lead should approve. The team-lead session died before any approval prompt rendered, matching the reported stack trace.
One downstream datapoint that may be useful for triage: on each crash, attached MCP servers disconnected entirely and their deferred tools dropped out of the remaining session. So the failure mode extends beyond "missing permission prompt", it cascades into losing any MCP tools the session was using, which blocks recovery paths that depend on those tools.
Downgrading to 2.1.110 per @cleong110's instructions (already cached locally at
~/.local/share/claude/versions/2.1.110, so no reinstall needed). Thanks for the detailed version bisection and downgrade recipe.Still hitting this on v2.1.113 (Apr 17 2026).
Repro:
teammateMode=tmux,CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1mode: "bypassPermissions"echo "hi"orpython3 -c "..."~/.claude/teams/<team>/inboxes/team-lead.jsonbut no approval UI rendersSendMessage {type:"shutdown_request"}can't recover, onlytmux kill-paneworksAttempted workarounds — none work:
mode: "bypassPermissions"on Agent spawn~/.claude/settings.json"defaultMode": "auto"~/.claude/settings.json"defaultMode": "bypassPermissions".claude/settings.jsonwith broadBash(python3:*)/Edit(...)/Write(...)allow rules.claude/settings.local.jsonwith the same rulesIs the fix landing in the next release? Current state is a hard block for any multi-agent workflow using sonnet teammates. Related: #26479, #43406, #24108.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.