stablyai/orca · warning · Error
Terminal input is locked by another client.
Error message
Terminal input is locked by another client.
What it means
Thrown in the terminal.send promise chain when the RPC succeeds (ok: true) but result.send.accepted === false. This means the desktop host explicitly rejected the terminal input because another client holds an input lock on that terminal. The terminal exists but its input is owned by a different session/client.
Source
Thrown at mobile/app/h/[hostId]/session/[worktreeId].tsx:3733
'terminal.send',
buildTerminalSendParams({
terminal: createdHandle,
text: options.initialPrompt,
enter: options.enter !== false,
deviceToken: deviceTokenRef.current
})
)
.then((sendResponse) => {
if (!sendResponse.ok) {
throw new Error(
(sendResponse as RpcFailure).error.message || 'Failed to send notes'
)
}
const result = (sendResponse as RpcSuccess).result as {
send?: { accepted?: boolean }
}
if (result.send?.accepted === false) {
throw new Error('Terminal input is locked by another client.')
}
triggerSuccess()
showToast(options.successToast ?? 'Notes sent')
options.onPromptSent?.()
})
.catch((err) => {
triggerError()
showToast(
options.errorToast ??
(err instanceof Error ? err.message : "Couldn't send notes"),
1800
)
})
} else if (options?.successToast) {
triggerSuccess()
showToast(options.successToast)
}
} else {View on GitHub (pinned to 1136503c6a)
Solutions
- Inform the user that the terminal is in use by another client and retry later.
- If the lock is stale (from a disconnected client), the desktop host should release it on session cleanup — reconnect or wait for timeout.
- Consider acquiring the input lock explicitly before sending, if the API supports it.
- Show the lock state in the UI so the user knows before attempting to send.
Example fix
// before: generic toast on lock rejection
.catch((err) => {
showToast(err.message, 1800)
})
// after: specific UX for input lock
.catch((err) => {
if (err.message.includes('locked by another client')) {
showToast('Terminal is busy in another session. Try again shortly.', 3000)
} else {
showToast(err.message, 1800)
}
}) Defensive patterns
Strategy: validation
Validate before calling
function isTerminalInputLocked(sendResponse) {
if (!sendResponse.ok) return false
const result = (sendResponse as RpcSuccess).result as { send?: { accepted?: boolean } }
return result?.send?.accepted === false
} Type guard
function isTerminalSendAccepted(response) {
if (!response.ok) return false
const result = (response as RpcSuccess).result as { send?: { accepted?: boolean } }
return result?.send?.accepted !== false
} Try / catch
.then((sendResponse) => {
if (!sendResponse.ok || isTerminalInputLocked(sendResponse)) {
throw new Error('Terminal input is locked by another client.')
}
triggerSuccess()
}).catch((err) => {
if (err.message.includes('locked by another client')) {
showToast('Terminal busy in another session. Try again shortly.', 3000)
} else {
showToast(err.message, 1800)
}
}) Prevention
- Show terminal lock state in the UI before the user attempts to send.
- Implement an explicit input-lock acquisition API so the client knows ownership before sending.
- Release the input lock on client disconnect to avoid stale locks.
When it happens
Trigger: terminal.send returns ok:true with result.send.accepted === false. Caused by: another mobile or desktop client has acquired exclusive input lock on the terminal; a previous client did not release the lock; the terminal is being driven by the desktop's own keyboard input.
Common situations: Multiple mobile devices connected to the same desktop session; the desktop user actively typing in the terminal while mobile tries to send; a stuck lock from a disconnected client that didn't clean up; concurrent quick-command execution from two clients.
Related errors
- Failed to send notes
- Failed to create terminal
- Created terminal response was invalid
- Terminal input is locked
- Terminal input is locked
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/1f5f8601ff683d10.
Report an issue: GitHub.