stablyai/orca · error

SSH target "${input.target.connectionId}" is not connected.

Error message

SSH target "${input.target.connectionId}" is not connected.

What it means

Thrown by listExternalAutomationRuns() on the remote branch when getActiveMultiplexer(input.target.connectionId) returns nothing (or a disposed multiplexer). The SSH connection backing the target must be live before Hermes run listings can be requested over it. This is the remote-path precondition; the local Hermes path does not need a mux.

Source

Thrown at src/main/automations/external-manager.ts:359

      runs: []
    }
  }
  if (input.target.type === 'local') {
    const result = await readHermesCronOutputRunsPage(input.jobId, { page, pageSize })
    return {
      managerId: input.managerId,
      provider: input.provider,
      target: input.target,
      jobId: input.jobId,
      page,
      pageSize,
      total: result.total,
      runs: mapHermesJobs(input.managerId, [{ id: input.jobId, runs: result.runs }])[0]?.runs ?? []
    }
  }
  const mux = getActiveMultiplexer(input.target.connectionId)
  if (!mux || mux.isDisposed()) {
    throw new Error(`SSH target "${input.target.connectionId}" is not connected.`)
  }
  const result = (await mux.request('externalAutomations.runs', {
    provider: input.provider,
    jobId: input.jobId,
    page,
    pageSize
  })) as { total?: number; runs?: unknown[] }
  return {
    managerId: input.managerId,
    provider: input.provider,
    target: input.target,
    jobId: input.jobId,
    page,
    pageSize,
    total: typeof result.total === 'number' && Number.isFinite(result.total) ? result.total : 0,
    runs:
      mapHermesJobs(input.managerId, [{ id: input.jobId, runs: result.runs ?? [] }])[0]?.runs ?? []
  }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Reconnect the SSH target (re-open the connection so getActiveMultiplexer returns a live mux) and retry.
  2. Guard the call: check the mux is alive before invoking, and prompt the user to reconnect if not.
  3. Verify input.target.connectionId matches an active, non-disposed multiplexer.

Example fix

// before
listExternalAutomationRuns({ target: { connectionId, type: 'remote' }, ... }) // mux gone -> throws

// after
const mux = getActiveMultiplexer(connectionId)
if (!mux || mux.isDisposed()) {
  await promptReconnect(connectionId)
  return
}
listExternalAutomationRuns({ target: { connectionId, type: 'remote' }, ... })
Defensive patterns

Strategy: validation

Validate before calling

import { getActiveMultiplexer } from '...'

function isSshTargetLive(connectionId: string): boolean {
  const mux = getActiveMultiplexer(connectionId)
  return Boolean(mux) && !mux!.isDisposed()
}

if (input.target.type === 'remote' && !isSshTargetLive(input.target.connectionId)) {
  await promptReconnect(input.target.connectionId)
  return
}
listExternalAutomationRuns(input)

Type guard

function isLiveMux(m: { isDisposed: () => boolean } | null | undefined): m is { isDisposed: () => boolean } {
  return Boolean(m) && !m!.isDisposed()
}

Try / catch

try {
  return await listExternalAutomationRuns(input)
} catch (e) {
  if (/SSH target ".+" is not connected\./.test((e as Error).message)) {
    await reconnect(input.target.connectionId)
    return await listExternalAutomationRuns(input)
  }
  throw e
}

Prevention

When it happens

Trigger: Listing runs for an SSH target whose connection dropped, was never opened, or whose multiplexer was disposed after the UI cached the target. Also if connectionId refers to a closed/disconnected session.

Common situations: SSH session timed out or the network dropped between opening the automation view and listing runs; user selected a target whose connection was closed in another pane; relay/SSH host restarted.

Related errors


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