{"record":{"id":"dc4fe703f87fc3c1","repo":"stablyai/orca","slug":"invalid-host-id-args-hostid","errorCode":null,"errorMessage":"Invalid host ID: ${args.hostId}","messagePattern":"Invalid host ID: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/repos.ts","lineNumber":2094,"sourceCode":"        return { status: 'applied' }\n      }\n      return { status: 'rejected' }\n    }\n  )\n\n  ipcMain.handle('repos:remove', async (_event, args: { repoId: string }) => {\n    store.removeProject(args.repoId)\n    invalidateAuthorizedRootsCache()\n    notifyReposChanged(mainWindow)\n  })\n\n  // Why: forget a project on one execution host without disturbing the same repo id on other hosts (SSH-workspace forget flow).\n  ipcMain.handle(\n    'repos:removeForHost',\n    async (_event, args: { repoId: string; hostId: string }) => {\n      const hostId = normalizeExecutionHostId(args.hostId)\n      if (!hostId) {\n        throw new Error(`Invalid host ID: ${args.hostId}`)\n      }\n      store.removeProjectForHost(args.repoId, hostId)\n      invalidateAuthorizedRootsCache()\n      notifyReposChanged(mainWindow)\n    }\n  )\n\n  ipcMain.handle(\n    'repos:update',\n    (\n      _event,\n      args: {\n        repoId: string\n        hostId?: ExecutionHostId\n        updates: Partial<\n          Pick<\n            Repo,\n            | 'displayName'","sourceCodeStart":2076,"sourceCodeEnd":2112,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/repos.ts#L2076-L2112","documentation":"Thrown by the repos:removeForHost IPC handler when normalizeExecutionHostId(args.hostId) returns null. normalizeExecutionHostId delegates to parseExecutionHostId and returns only the canonical id string, so the same three valid forms apply (local literal, ssh:<encoded>, runtime:<encoded>). This handler exists to forget a project on one host without disturbing the same repo id elsewhere.","triggerScenarios":"Sending a hostId that is undefined/null/empty, a bare target/environment id, or a malformed prefixed string. Because removeForHost must scope the deletion to one host, an unresolvable host id is fatal rather than defaulted to 'all hosts'.","commonSituations":"A 'forget' action whose host context was lost (e.g. the row was rendered for a host that disconnected); passing the repo's host field verbatim when it actually stores a target id; renderer reused an all-hosts sentinel where a concrete id was required.","solutions":["Resolve the host id via normalizeExecutionHostId in the renderer and block the action if it is null.","Use toSshExecutionHostId / toRuntimeExecutionHostId to build the id from a stored target/environment id.","If the host is gone, fall back to repos:remove only after explicit user confirmation (it affects all hosts).","Ensure the host context is captured when the project row is created, not recomputed lazily."],"exampleFix":"// before\nipc.invoke('repos:removeForHost', { repoId, hostId: targetId })\n\n// after\nimport { normalizeExecutionHostId } from '@shared/execution-host'\nconst hostId = normalizeExecutionHostId(rawHost)\nif (!hostId) {\n  showError('This host can no longer be identified.')\n  return\n}\nipc.invoke('repos:removeForHost', { repoId, hostId })","handlingStrategy":"type-guard","validationCode":"import { normalizeExecutionHostId } from '@shared/execution-host'\n\nconst hostId = normalizeExecutionHostId(rawHostId)\nif (!hostId) {\n  showError('Cannot forget on this host: host identity is missing.')\n  return\n}\nawait ipc.invoke('repos:removeForHost', { repoId, hostId })","typeGuard":"import { normalizeExecutionHostId } from '@shared/execution-host'\n\nfunction isConcreteHostId(value: unknown): value is string {\n  return typeof value === 'string' && normalizeExecutionHostId(value) !== null\n}","tryCatchPattern":"try {\n  await ipc.invoke('repos:removeForHost', { repoId, hostId })\n} catch (e) {\n  if (/Invalid host ID/.test((e as Error).message)) {\n    promptForgetAllHosts(repoId) // fallback after explicit consent\n  } else throw e\n}","preventionTips":["Bind the host id to the project row at render time and pass it through verbatim.","Do not default to all-hosts removal when the host id is missing; ask the user.","Validate with normalizeExecutionHostId before invoking."],"tags":["ipc","repos","execution-host","validation","ssh-workspace"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}