{"record":{"id":"8bc61392f5ced3b6","repo":"Hmbown/CodeWhale","slug":"unknown-transport-computer-transport","errorCode":null,"errorMessage":"unknown transport ${computer.transport}","messagePattern":"unknown transport (.+?)","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/transport.mjs","lineNumber":349,"sourceCode":"  if (computer.transport === \"local\") {\n    // Test hook: exercise the out-of-process wire path (desktop app / ssh\n    // agent) in-process, so wire argument preparation is covered by tests.\n    if (process.env.CODEWHALE_CU_TEST_REMOTE === \"1\") {\n      const { handle } = await import(\"./app-handler.mjs\");\n      return { ...appExec({ id: \"test\", name: \"test app\" }), remote: (request) => handle(request, { sessionId: SESSION_ID, signal: currentSignal() }) };\n    }\n    const status = await ensureApp();\n    if (status.via === \"app\") {\n      if (status.app.sessionProtocol !== 2) throw Object.assign(new ExecError(\"The installed Computer Use helper needs an update for isolated sessions and disconnect cleanup. Rebuild/reinstall it, then retry.\"), { code: \"app_upgrade_required\" });\n      if (process.platform === \"darwin\" && status.app.backgroundProtocol !== 1) throw Object.assign(new ExecError(\"The installed Computer Use app predates background scrolling, scoped observations and foreground preemption. Update and restart the helper before using it.\"), { code: \"app_upgrade_required\" });\n      return appExec(status.app);\n    }\n    return { ...localExec(), appReason: status.reason };\n  }\n  if (computer.transport === \"ssh\") return sshExec(computer, binding);\n  if (computer.transport === \"docker\") return dockerExec(computer, binding);\n  if (computer.transport === \"hdc\") return hdcExec(computer);\n  throw new ExecError(`unknown transport ${computer.transport}`);\n}\n\n/**\n * Map a computer to its backend module. Local platform is fixed; ssh\n * computers may carry platformHint (probed at registration).\n */\nfunction effectivePlatform(computer) {\n  let platform = computer.platform ?? computer.platformHint;\n  if (!platform) {\n    if (computer.transport === \"local\") platform = process.platform;\n    else if (computer.transport === \"hdc\") platform = \"harmonyos\";\n    else if (computer.transport === \"docker\") platform = \"linux\"; // spawned containers are always the Linux desktop image\n    else platform = \"linux\"; // conservative default for ssh; registration probes it\n  }\n  return platform;\n}\n\n/** Identity of the effective route, excluding catalog presentation metadata. */","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/transport.mjs#L331-L367","documentation":"executorFor() dispatches a computer binding to its transport implementation (local, ssh, docker, hdc) and throws this ExecError for any transport value outside the supported set. It is a fail-loud guard against misconfigured computer registrations, per the misconfiguration-fails-loud convention.","triggerScenarios":"Calling executorFor(computer) where computer.transport is anything other than \"ssh\"|\"docker\"|\"hdc\" (and not handled by the local path above): typos like \"local\", \"docker2\", null/undefined transport, or stale saved config from an older schema.","commonSituations":"Typo in a config file's transport field; config written by hand or by an older plugin version using a removed transport name; programmatically constructed binding with a wrong string; JSON config with casing differences (\"SSH\" vs \"ssh\").","solutions":["Fix computer.transport in the config to one of: ssh, docker, hdc (or a valid local setup)","Check for case/typo mistakes — the value is matched exactly","If migrating from an older config, update the transport name to the current set","Add validation at config-load time to reject unknown transports early","Log/inspect the actual computer object to see the offending value"],"exampleFix":"// before\n{ \"computer\": { \"transport\": \"ssh \" } } // trailing space -> unknown transport\n// after\n{ \"computer\": { \"transport\": \"ssh\" } }","handlingStrategy":"validation","validationCode":"const SUPPORTED = new Set([\"ssh\", \"docker\", \"hdc\"]);\nif (!SUPPORTED.has(computer?.transport)) throw new Error(`transport must be one of ssh|docker|hdc, got ${computer?.transport}`);\nconst ex = executorFor(computer);","typeGuard":"function isKnownTransport(c) { return c && [\"ssh\", \"docker\", \"hdc\"].includes(c.transport); }","tryCatchPattern":"try {\n  const ex = executorFor(computer);\n} catch (e) {\n  if (e.message.startsWith(\"unknown transport\")) {\n    console.error(`bad transport in binding: ${JSON.stringify(computer)}`); // fail loud, show config\n    throw e;\n  }\n  throw e;\n}","preventionTips":["Validate computer bindings at config load, before dispatch","Use only exact lowercase transport names: ssh, docker, hdc","Trim user-supplied config strings to avoid trailing-space mismatches","Migrate configs from removed transports to the current set"],"tags":["configuration","invalid-value","dispatch"],"backgroundTag":"invalid-enum-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}