hcengineering/platform · info
force-close-unknown
Error message
force-close-unknown
What it means
Warning emitted by TSessionManager.forceClose when the requested wsId is NOT present in this.workspaces — there is nothing to close on this node. The workspace caches (maintenanceWorkspaces, workspaceInfoCache) are still cleared, so this typically indicates the caller acted on stale state or the workspace lives on another server node.
Source
Thrown at foundations/server/packages/server/src/sessionManager.ts:1191
workspace.maintenance = true
ctx.info('force-maintenance', { workspaceId })
await this.doCloseAll(workspace, 99, 'force-close')
}
}
async forceClose (wsId: WorkspaceUuid, ignoreSocket?: ConnectionSocket): Promise<void> {
const ws = this.workspaces.get(wsId)
this.maintenanceWorkspaces.delete(wsId)
this.workspaceInfoCache.delete(wsId)
if (ws !== undefined) {
this.ctx.warn('force-close', { name: ws.wsId.url })
ws.maintenance = true // We need to similare upgrade to refresh all clients.
ws.closing = this.doCloseAll(ws, 99, 'force-close', ignoreSocket)
this.workspaces.delete(wsId)
await ws.closing
ws.closing = undefined
} else {
this.ctx.warn('force-close-unknown', { wsId })
}
}
async doCloseAll (
workspace: Workspace,
code: number,
reason: 'upgrade' | 'shutdown' | 'force-close',
ignoreSocket?: ConnectionSocket
): Promise<void> {
if (LOGGING_ENABLED) {
this.ctx.info('closing workspace', {
url: workspace.wsId.url,
uuid: workspace.wsId.uuid,
code,
reason
})
}
View on GitHub (pinned to 63e28dc964)
Solutions
- Usually harmless — the caches are cleaned anyway; confirm the workspace is not expected on this node.
- Check the workspace service routing: ensure close requests go to the node actually hosting the workspace.
- Look for duplicate/concurrent forceClose calls for the same wsId and add idempotency or locking in the caller.
- If the workspace should have been present, investigate why it was closed earlier (errors in close path, idle eviction).
Example fix
// before: fire-and-forget close to any node await Promise.all(nodes.map(n => n.forceClose(wsId))) // after: route to the owning node only const owner = await workspaceService.getNode(wsId) await owner.forceClose(wsId)
Defensive patterns
Strategy: validation
Validate before calling
const loaded = sessionManager.workspaces.get(wsId)
if (loaded === undefined) {
console.warn('workspace not loaded on this node; skip forceClose or route to owner node')
} Type guard
function isTracked(ws: Workspace | undefined): ws is Workspace {
return ws !== undefined
} Try / catch
try {
await sessionManager.forceClose(wsId)
} catch (err) {
logger.warn('force-close on unknown workspace is a no-op', { wsId, err })
} Prevention
- Route close requests to the node currently hosting the workspace (query the workspace service registry).
- Make close orchestration idempotent so retries don't log spurious unknown-workspace entries.
- Refresh the workspace registry after closes to avoid acting on stale routing.
- Deduplicate concurrent close requests for the same wsId.
When it happens
Trigger: forceClose(wsId) invoked while this.workspaces.get(wsId) === undefined: workspace already closed/evicted, never loaded on this node, or already force-closed concurrently.
Common situations: Double force-close from racing admin operations or a retry; stale workspace registry entry pointing at the wrong node; workspace closed by idle timeout just before the close request arrived.
Related errors
- open workspace
- reconnect workspace in upgrade switch
- force-close
- Workspace closed...
- no sessions for workspace
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/1cfab5eabfdd66e9.
Report an issue: GitHub.