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

  1. Inform the user that the terminal is in use by another client and retry later.
  2. If the lock is stale (from a disconnected client), the desktop host should release it on session cleanup — reconnect or wait for timeout.
  3. Consider acquiring the input lock explicitly before sending, if the API supports it.
  4. 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

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


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/1f5f8601ff683d10. Report an issue: GitHub.