stablyai/orca · error
Couldn't verify the SSH connection. Reconnect the host and t
Error message
Couldn't verify the SSH connection. Reconnect the host and try again.
What it means
Thrown by buildMobileFileMutationOwnership when worktreeHostId is a defined non-undefined value but parseExecutionHostId could not parse it into a recognized host (local | runtime | ssh). This guards against committing a file mutation to a host whose execution identity the client cannot interpret — writing through an ambiguous host id would risk mutating the wrong machine.
Source
Thrown at mobile/src/files/mobile-file-mutation-ownership.ts:22
import type { SshConnectionState, SshMutationExpectation } from '../../../src/shared/ssh-types'
import type { RpcClient } from '../transport/rpc-client'
import type { RpcFailure, RpcSuccess } from '../transport/types'
const FILE_MUTATION_TIMEOUT_MS = 15_000
const SSH_OWNER_CHANGED_MESSAGE =
"Couldn't verify the SSH connection. Reconnect the host and try again."
export type MobileFileMutationOwnership = SshMutationExpectation & {
expectedExecutionHostId: 'local' | `ssh:${string}`
}
export function buildMobileFileMutationOwnership(
worktreeHostId: string | null | undefined,
sshState: SshConnectionState | null = null
): MobileFileMutationOwnership {
const host = parseExecutionHostId(worktreeHostId)
if (worktreeHostId !== undefined && !host) {
throw new Error(SSH_OWNER_CHANGED_MESSAGE)
}
if (!host || host.kind === 'local' || host.kind === 'runtime') {
return { expectedExecutionHostId: 'local' }
}
if (sshState?.targetId !== host.targetId || sshState.connectionGeneration === undefined) {
throw new Error(SSH_OWNER_CHANGED_MESSAGE)
}
return {
expectedExecutionHostId: host.id,
expectedSshTargetId: host.targetId,
expectedSshConnectionGeneration: sshState.connectionGeneration
}
}
export async function captureMobileFileMutationOwnership(
client: Pick<RpcClient, 'sendRequest'>,
worktree: string
): Promise<MobileFileMutationOwnership> {View on GitHub (pinned to 1136503c6a)
Solutions
- Update the mobile app so parseExecutionHostId understands the new host-kind prefix.
- If worktreeHostId came from worktree.show, re-fetch it — a corrupt value often indicates a stale worktree row; rotate the worktree.
- Treat as 'reconnect the host': the SSH_OWNER_CHANGED_MESSAGE tells the user to re-establish the host connection so a fresh, parseable hostId is captured.
- If the hostId is genuinely a new kind and updating is not possible, block mutations on that worktree until the app is upgraded.
Example fix
// before
const host = parseExecutionHostId(worktreeHostId)
if (worktreeHostId !== undefined && !host) {
throw new Error(SSH_OWNER_CHANGED_MESSAGE)
}
// after — distinguish 'new kind' from 'corrupt' for clearer UX
const host = parseExecutionHostId(worktreeHostId)
if (worktreeHostId !== undefined && !host) {
if (typeof worktreeHostId === 'string' && worktreeHostId.includes(':')) {
throw new Error(`Unsupported host kind: ${worktreeHostId.split(':')[0]}. Update the app.`)
}
throw new Error(SSH_OWNER_CHANGED_MESSAGE)
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the host id is parseable before building ownership
import { parseExecutionHostId } from '../../../src/shared/execution-host'
if (worktreeHostId !== undefined && !parseExecutionHostId(worktreeHostId)) {
throw new Error('Cannot mutate files: unrecognized host id. Reconnect the host.')
} Type guard
function isRecognizedHostId(id: string | null | undefined): boolean {
if (id === undefined || id === null) return true
return parseExecutionHostId(id) !== null
} Try / catch
try {
return buildMobileFileMutationOwnership(worktreeHostId, sshState)
} catch (err) {
if (err instanceof Error && err.message === SSH_OWNER_CHANGED_MESSAGE) {
await forceReconnect()
const fresh = await captureMobileFileMutationOwnership(client, worktree)
return fresh
}
throw err
} Prevention
- Treat unparseable host ids as a hard stop — never fall back to 'local'.
- When a new host-kind prefix is introduced, update parseExecutionHostId in lockstep.
- Re-capture ownership via captureMobileFileMutationOwnership after any host reconnect.
When it happens
Trigger: buildMobileFileMutationOwnership(worktreeHostId, sshState) is called with worktreeHostId that is defined (not undefined) but not 'local', not a 'runtime:...' id, and not an 'ssh:...' id. Concretely: a malformed host string from worktree.show, a new host-kind prefix the client build does not yet understand, or a corrupted persisted host id.
Common situations: A newer desktop build introduces a new execution-host kind (e.g., 'container:...') that this mobile build's parseExecutionHostId does not recognize; a worktree.show result with a truncated or corrupt hostId; an old mobile app paired with a newer desktop that emits a different host id scheme.
Related errors
- ${RPC error message}
- ${label} is required
- Upload source changed while being inspected: ${sourcePath}
- No SSH connection for "${connectionId}"
- SSH connection is not active — please reconnect and try agai
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/68186440bdf13072.
Report an issue: GitHub.