stablyai/orca · error · Error
Unexpected helper handshake
Error message
Unexpected helper handshake: ${JSON.stringify(capabilities)} What it means
After the helper appears, the sidecar's capabilities RPC must report protocolVersion === 1. Any other value (or a capabilities object missing protocolVersion, caught by the optional chain) means the helper speaks a different protocol version than this benchmark expects, so the session is not 'authenticated' in the sense the test relies on. The full capabilities payload is serialized into the message.
Solutions
- Read protocolVersion from the JSON in the message to see what the helper actually reported.
- Align helper and sidecar to the same release so both speak protocolVersion 1.
- If the protocol was intentionally bumped, update the benchmark's expected version constant from 1.
Example fix
// before
if (capabilities?.protocolVersion !== 1) {
throw new Error(`Unexpected helper handshake: ${JSON.stringify(capabilities)}`)
}
// after
const EXPECTED_PROTOCOL = 1
if (capabilities?.protocolVersion !== EXPECTED_PROTOCOL) {
throw new Error(`Helper protocol ${capabilities?.protocolVersion} != expected ${EXPECTED_PROTOCOL}: ${JSON.stringify(capabilities)}`)
} Defensive patterns
Strategy: validation
Validate before calling
const EXPECTED_PROTOCOL = 1
if (capabilities?.protocolVersion !== EXPECTED_PROTOCOL) {
throw new Error(`Helper protocol ${capabilities?.protocolVersion} != ${EXPECTED_PROTOCOL}`)
} Type guard
const isExpectedHandshake = (c, expected = 1) => c?.protocolVersion === expected
Try / catch
try {
await startAuthenticatedSession()
} catch (e) {
if (/Unexpected helper handshake/.test(e.message)) { /* align helper/sidecar versions, rerun */ }
throw e
} Prevention
- Keep helper and sidecar on the same release so protocolVersion matches.
- Centralize EXPECTED_PROTOCOL in one constant both sides read.
- Add an integration test asserting the handshake version on each release.
When it happens
Trigger: A newer or older helper binary whose protocolVersion is 2/0/undefined, a capabilities response that failed and surfaced as error (re-thrown first), or a sidecar that returned an unexpected envelope shape.
Common situations: Helper/sidecar version skew (one updated without the other), a local helper build with a bumped protocol version, or a regression where capabilities omits protocolVersion.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- provider_incompatible
- agent_session_identity_required
- Artifact share records have an unsupported format.
- Could not find helper owned by sidecar
- Could not read helper socket path from command
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/eeb0400fe2894f10.
Report an issue: GitHub.
Appendix: source
Thrown at config/scripts/macos-computer-helper-owner-loss-benchmark.mjs:276
const sidecar = startSidecar()
let helper
try {
const capabilitiesResult = requestSidecar(sidecar, 1, 'capabilities').then(
(capabilities) => ({ capabilities }),
(error) => ({ error })
)
helper = await waitForHelper(sidecar.child.pid)
const helperRecordPath = process.env[HELPER_RECORD_PATH_ENV]
if (!helperRecordPath) {
throw new Error('Missing helper process record path')
}
writeProcessRecord(helperRecordPath, helper)
const { capabilities, error } = await capabilitiesResult
if (error) {
throw error
}
if (capabilities?.protocolVersion !== 1) {
throw new Error(`Unexpected helper handshake: ${JSON.stringify(capabilities)}`)
}
return { authenticated: capabilities.protocolVersion === 1, sidecar, helper }
} catch (error) {
sidecar.child.kill('SIGKILL')
await stopProcess(helper)
throw error
}
}
async function exerciseActiveRequests(sidecar) {
const latencies = []
const startedAt = performance.now()
for (let index = 0; index < ACTIVE_REQUEST_COUNT; index += 1) {
const requestStartedAt = performance.now()
const result = await requestSidecar(sidecar, 10_000 + index, 'listApps')
if (!Array.isArray(result?.apps)) {
throw new Error(`Unexpected listApps response: ${JSON.stringify(result)}`)
}View on GitHub (pinned to 1136503c6a)