stablyai/orca · error · Error
Terminal input is locked
Error message
Terminal input is locked
What it means
Same reader as 386 but on the notes-send path: `terminal.send` succeeded (ok:true) yet result.send.accepted === false. The host accepted the envelope but refused the keystrokes because the terminal input is owned/locked.
Source
Thrown at mobile/src/session/use-mobile-diff-review-send-actions.ts:92
async (terminal: string, comments: readonly DiffComment[]) => {
if (!client || connState !== 'connected') {
throw new Error('Waiting for desktop...')
}
// Marked by terminal handle, not by surface, so a paste orphaned here by native
// chat would ride along with these notes (#10228). Diff review carries no device token.
if (!(await healMobileNativeChatStaleInput({ client, terminal, deviceToken: null }))) {
throw new Error('Failed to send notes')
}
const response = await client.sendRequest('terminal.send', {
terminal,
text: formatMobileDiffReviewPrompt(comments),
enter: true
})
if (!response.ok) {
throw new Error(response.error?.message || 'Failed to send notes')
}
if (!readMobileReviewTerminalSendAccepted(response.result)) {
throw new Error('Terminal input is locked')
}
await markNotesSent(comments)
triggerSuccess()
setActionError('Review notes sent')
setSendSheet(null)
},
[client, connState, markNotesSent, setActionError, setSendSheet]
)
const createTerminalAndSend = useCallback(
async (comments: readonly DiffComment[]) => {
if (!client || connState !== 'connected') {
throw new Error('Waiting for desktop...')
}
const response = await client.sendRequest('session.tabs.createTerminal', {
worktree: `id:${worktreeId}`,
activate: false,
select: true,View on GitHub (pinned to 1136503c6a)
Solutions
- Close competing native chat on that terminal.
- Retry the send.
- Pick a different terminal / create a fresh one.
- Heal stale input again.
Example fix
// before
if (!readMobileReviewTerminalSendAccepted(response.result)) {
throw new Error('Terminal input is locked')
}
// after - fall back to a fresh terminal
if (!readMobileReviewTerminalSendAccepted(response.result)) {
return createTerminalAndSend(comments)
} Defensive patterns
Strategy: retry
Validate before calling
if (isMobileNativeChatInputStale(terminal)) {
await healMobileNativeChatStaleInput({ client, terminal, deviceToken: null })
} Type guard
function readMobileReviewTerminalSendAccepted(value: unknown): boolean {
if (!isRecord(value) || !isRecord(value.send)) return true
return value.send.accepted !== false
} Try / catch
try {
await sendPromptToTerminal(terminal, comments)
} catch (err) {
if (/locked/.test(err instanceof Error ? err.message : '')) {
return createTerminalAndSend(comments)
}
throw err
} Prevention
- Heal stale input before sending.
- Prefer freshly-created terminals.
- Avoid terminals owned by active native chat.
When it happens
Trigger: A native chat composer or another surface owns the terminal input line; an overlay has focus; the stale-input heal consumed the marker but the lock returned.
Common situations: Native chat left the line owned; two send surfaces target the same terminal; host lock state stale.
Related errors
- Terminal input is locked
- Waiting for desktop...
- Failed to send notes
- Unable to load agent sessions
- Terminal input is locked by another client.
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/ee77d904a4ad33af.
Report an issue: GitHub.