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

  1. Usually harmless — the caches are cleaned anyway; confirm the workspace is not expected on this node.
  2. Check the workspace service routing: ensure close requests go to the node actually hosting the workspace.
  3. Look for duplicate/concurrent forceClose calls for the same wsId and add idempotency or locking in the caller.
  4. 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

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


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/1cfab5eabfdd66e9. Report an issue: GitHub.