deepseek-ai/deepseek-harness · error
sessions.selectSubagent: ${address.childSessionId} is not a
Error message
sessions.selectSubagent: ${address.childSessionId} is not a healthy catalog child What it means
SessionsManager.selectSubagent re-validates a SubagentAddress against the cached subagent catalog of its parent session before selecting. It throws when no catalog is loaded for address.parentSessionId (so the entry lookup yields undefined), when the child id is absent from catalog.entries, when the entry's kind is not 'child', or when entry.mode differs from address.mode. The guard exists because addresses are durable and catalog-derived: a stale, persisted, or hand-built address must never gain selection authority over the live roster truth.
Source
Thrown at packages/client/runtime/src/client/sessions/manager.ts:212
? false
: this.catalogs.get(address.parentSessionId)?.parentAvailable ?? false,
)
this.selected = sessionId
// Looking at the session consumes its completion reminder (dot clears).
this.completedNotifications.delete(sessionId)
void this.refreshSubagents(sessionId)
this.notifier.notifyNow()
}
/**
* Select a healthy child through its durable direct-parent address.
* @param address - catalog-derived parent and child ids.
*/
selectSubagent(address: SubagentAddress): void {
const catalog = this.catalogs.get(address.parentSessionId)
const entry = catalog?.entries.find(candidate => candidate.id === address.childSessionId)
if (entry === undefined || entry.kind !== 'child' || entry.mode !== address.mode) {
throw new Error(`sessions.selectSubagent: ${address.childSessionId} is not a healthy catalog child`)
}
this.addresses.set(address.childSessionId, address)
this.sessions.get(address.childSessionId)?.configureSubagent(address, catalog?.parentAvailable ?? false)
this.selected = address.childSessionId
this.completedNotifications.delete(address.childSessionId)
void this.refreshSubagents(address.childSessionId)
this.notifier.notifyNow()
}
/** Clear the selection (the layout falls to the no-session view state). */
clearSelection(): void {
this.selected = undefined
this.notifier.notifyNow()
}
/**
* Return the durable catalog address retained for one child.
* @param sessionId - possible addressed child id.View on GitHub (pinned to b150a551b8)
Solutions
- Re-derive the address from the current catalog, or use manager.select(childSessionId) which resolves a retained or catalog-derived address leniently through navigationAddress and only throws when the session is neither listed nor addressable
- Ensure the parent catalog is loaded before offering subagent navigation: open or refresh the parent session first and wait for its catalog pull
- Copy the mode field from the catalog entry when constructing the address, never from a constant or persisted string
- Invalidate cached addresses on roster/catalog change events and re-read entries before any selection
Example fix
// before — replaying an address captured earlier manager.selectSubagent(staleAddress) // after — lenient selection that re-derives the address from loaded catalogs manager.select(staleAddress.childSessionId)
Defensive patterns
Strategy: try-catch
Try / catch
try {
manager.selectSubagent(address)
} catch (error) {
if (error instanceof Error && error.message.startsWith('sessions.selectSubagent:')) {
// stale address: fall back to lenient selection, which re-derives from loaded catalogs
manager.select(address.childSessionId)
} else {
throw error
}
} Prevention
- Derive SubagentAddress values from the live catalog entry at click time — entry.id, entry.mode, and the owning parentSessionId
- Drop cached addresses on roster or catalog changes instead of persisting them across reloads
- Confirm the parent session's catalog finished loading before offering subagent navigation
- Never hand-write mode strings; copy entry.mode
When it happens
Trigger: Calling sessions.openSubagent/selectSubagent with (a) an address captured from an earlier catalog snapshot after the child finished, changed mode, or was removed by a roster change; (b) an address for a parent whose catalog has not been pulled yet (this.catalogs has no entry, so entry is undefined); (c) a mode mismatch, e.g. address.mode 'agent' against entry.mode 'task'; (d) a wrong parentSessionId so the lookup scans another parent's catalog or none.
Common situations: Caching SubagentAddress values across catalog refreshes or page reloads; clicking a subagent row in the same tick a roster change removes it; restoring a persisted address at startup before refreshSubagents has pulled the parent catalog; test fixtures hand-crafting addresses instead of deriving them from catalog entries.
Related errors
- agent-busy
- session.models failed: ${result.error.code}: ${result.error.
- this provider's catalog failed to load — pick a model from a
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/455f318ed4bf340f.
Report an issue: GitHub.