stablyai/orca · error · Error
Invalid host ID: ${args.hostId}
Error message
Invalid host ID: ${args.hostId} What it means
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.
Source
Thrown at src/main/ipc/repos.ts:2094
return { status: 'applied' }
}
return { status: 'rejected' }
}
)
ipcMain.handle('repos:remove', async (_event, args: { repoId: string }) => {
store.removeProject(args.repoId)
invalidateAuthorizedRootsCache()
notifyReposChanged(mainWindow)
})
// Why: forget a project on one execution host without disturbing the same repo id on other hosts (SSH-workspace forget flow).
ipcMain.handle(
'repos:removeForHost',
async (_event, args: { repoId: string; hostId: string }) => {
const hostId = normalizeExecutionHostId(args.hostId)
if (!hostId) {
throw new Error(`Invalid host ID: ${args.hostId}`)
}
store.removeProjectForHost(args.repoId, hostId)
invalidateAuthorizedRootsCache()
notifyReposChanged(mainWindow)
}
)
ipcMain.handle(
'repos:update',
(
_event,
args: {
repoId: string
hostId?: ExecutionHostId
updates: Partial<
Pick<
Repo,
| 'displayName'View on GitHub (pinned to 1136503c6a)
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.
Example fix
// before
ipc.invoke('repos:removeForHost', { repoId, hostId: targetId })
// after
import { normalizeExecutionHostId } from '@shared/execution-host'
const hostId = normalizeExecutionHostId(rawHost)
if (!hostId) {
showError('This host can no longer be identified.')
return
}
ipc.invoke('repos:removeForHost', { repoId, hostId }) Defensive patterns
Strategy: type-guard
Validate before calling
import { normalizeExecutionHostId } from '@shared/execution-host'
const hostId = normalizeExecutionHostId(rawHostId)
if (!hostId) {
showError('Cannot forget on this host: host identity is missing.')
return
}
await ipc.invoke('repos:removeForHost', { repoId, hostId }) Type guard
import { normalizeExecutionHostId } from '@shared/execution-host'
function isConcreteHostId(value: unknown): value is string {
return typeof value === 'string' && normalizeExecutionHostId(value) !== null
} Try / catch
try {
await ipc.invoke('repos:removeForHost', { repoId, hostId })
} catch (e) {
if (/Invalid host ID/.test((e as Error).message)) {
promptForgetAllHosts(repoId) // fallback after explicit consent
} else throw e
} Prevention
- 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.
When it happens
Trigger: 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'.
Common situations: 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.
Related errors
- Unsupported host: ${args.hostId}
- Repo path must be an absolute path
- Preset name is required.
- Preset name is too long.
- Preset directories must be repo-relative paths.
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/dc4fe703f87fc3c1.
Report an issue: GitHub.