{"record":{"id":"91ea3a70252db00a","repo":"stablyai/orca","slug":"failed-to-create-terminal-91ea3a","errorCode":null,"errorMessage":"Failed to create terminal","messagePattern":"Failed to create terminal","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mobile/src/session/pr-ai-triage-launch.ts","lineNumber":25,"sourceCode":"// Pure launch path for the PR triage actions (\"Fix checks with AI\" / \"Resolve\n// conflicts with AI\"). Reuses the same two RPCs the diff-review send flow uses —\n// session.tabs.createTerminal then terminal.send — so the prompt is dropped into a\n// fresh agent terminal in the worktree. There is no higher-level agent-composer RPC\n// on mobile, so this createTerminal+send pair is the launch mechanism. Kept free of\n// react-native imports so it stays unit-testable in the node test environment.\nexport async function createTerminalAndSendPrompt(\n  client: Pick<RpcClient, 'sendRequest'>,\n  worktreeId: string,\n  prompt: string\n): Promise<void> {\n  const created = await client.sendRequest('session.tabs.createTerminal', {\n    worktree: `id:${worktreeId}`,\n    activate: false,\n    select: true,\n    navigation: 'caller'\n  })\n  if (!created.ok) {\n    throw new Error(created.error?.message || 'Failed to create terminal')\n  }\n  const terminalTab = readMobileReviewCreatedTerminal(created.result)\n  if (!terminalTab) {\n    throw new Error('Created terminal response was invalid')\n  }\n  const sent = await client.sendRequest('terminal.send', {\n    terminal: terminalTab.terminal,\n    text: prompt,\n    enter: true\n  })\n  if (!sent.ok) {\n    throw new Error(sent.error?.message || 'Failed to send prompt')\n  }\n  if (!readMobileReviewTerminalSendAccepted(sent.result)) {\n    throw new Error('Terminal input is locked')\n  }\n}\n","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/mobile/src/session/pr-ai-triage-launch.ts#L7-L43","documentation":"Thrown by the PR AI triage launcher when `session.tabs.createTerminal` returns a failure. This is step one of the create-terminal-then-send-prompt launch used by 'Fix checks with AI' / 'Resolve conflicts with AI'. The host's error.message is preferred; the literal string is the fallback when the host gave no message.","triggerScenarios":"The host refuses to create a terminal in the target worktree - worktree missing/disposed, terminal quota reached, the worktree id no longer resolves; or a transport/relay failure on the one-shot.","commonSituations":"The worktree was deleted on the host while the mobile review screen was open; host terminal limit hit; relay cutover mid-launch; version skew where the host does not accept navigation:'caller'.","solutions":["Retry after reconnecting.","Verify the worktree still exists on the host.","Check the host terminal count / quota.","Update client and host to compatible versions."],"exampleFix":"// before\nif (!created.ok) {\n  throw new Error(created.error?.message || 'Failed to create terminal')\n}\n// after - carry the host error code so callers can branch\nif (!created.ok) {\n  throw new RpcMethodError('session.tabs.createTerminal', created.error)\n}","handlingStrategy":"try-catch","validationCode":"if (!client || connState !== 'connected') throw new Error('Waiting for desktop...')","typeGuard":"function isRpcFailure(r: RpcResponse): r is RpcFailure {\n  return r.ok === false\n}","tryCatchPattern":"try {\n  await createTerminalAndSendPrompt(client, worktreeId, prompt)\n} catch (err) {\n  setTriageError(err instanceof Error ? err.message : 'Could not start AI triage')\n}","preventionTips":["Gate the launch on connState==='connected'.","Refresh the worktree list before offering triage actions.","Retry once on relay cutover, then surface the error."],"tags":["rpc","terminal","create-terminal","pr-triage","mobile"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}