{"record":{"id":"b3e0ee80004c77a5","repo":"hcengineering/platform","slug":"force-close","errorCode":null,"errorMessage":"force-close","messagePattern":"force-close","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"foundations/server/packages/server/src/sessionManager.ts","lineNumber":1184,"sourceCode":"    }\n  }\n\n  async forceMaintenance (ctx: MeasureContext, workspaceId: WorkspaceUuid): Promise<void> {\n    const workspace = this.workspaces.get(workspaceId)\n    this.maintenanceWorkspaces.add(workspaceId)\n    if (workspace !== undefined) {\n      workspace.maintenance = true\n      ctx.info('force-maintenance', { workspaceId })\n      await this.doCloseAll(workspace, 99, 'force-close')\n    }\n  }\n\n  async forceClose (wsId: WorkspaceUuid, ignoreSocket?: ConnectionSocket): Promise<void> {\n    const ws = this.workspaces.get(wsId)\n    this.maintenanceWorkspaces.delete(wsId)\n    this.workspaceInfoCache.delete(wsId)\n    if (ws !== undefined) {\n      this.ctx.warn('force-close', { name: ws.wsId.url })\n      ws.maintenance = true // We need to similare upgrade to refresh all clients.\n      ws.closing = this.doCloseAll(ws, 99, 'force-close', ignoreSocket)\n      this.workspaces.delete(wsId)\n      await ws.closing\n      ws.closing = undefined\n    } else {\n      this.ctx.warn('force-close-unknown', { wsId })\n    }\n  }\n\n  async doCloseAll (\n    workspace: Workspace,\n    code: number,\n    reason: 'upgrade' | 'shutdown' | 'force-close',\n    ignoreSocket?: ConnectionSocket\n  ): Promise<void> {\n    if (LOGGING_ENABLED) {\n      this.ctx.info('closing workspace', {","sourceCodeStart":1166,"sourceCodeEnd":1202,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/server/src/sessionManager.ts#L1166-L1202","documentation":"Warning emitted by TSessionManager.forceClose when a workspace is found for the given wsId and is being force-closed: the workspace is marked maintenance (to simulate an upgrade so all clients refresh), doCloseAll is started with close code 99 and reason 'force-close', and the workspace is removed from this.workspaces. This is an administrative teardown, typically of a stuck or misbehaving workspace.","triggerScenarios":"forceClose(wsId, ignoreSocket?) called (e.g., by admin tooling or the workspace service) while this.workspaces.get(wsId) !== undefined. All sessions except ignoreSocket get an upgrade notification then a close(99, 'force-close').","commonSituations":"Operator force-closing a wedged workspace; workspace service instructing a node to drop a workspace after a failed upgrade; cleaning up before a workspace restart or migration.","solutions":["Expected on admin teardown — clients will receive code 99 and reconnect, hitting the 'connect during upgrade' path until maintenance is cleared.","Verify clients reconnect successfully afterwards; if they loop, check whether maintenanceWorkspaces/workspaceInfoCache state is stale.","Investigate why the force-close was needed (stuck sessions, hung requests) using the statistics/health endpoints.","If forceClose was called unintentionally, audit the admin tooling/automation that invoked it."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const ws = sessionManager.workspaces.get(wsId)\nif (ws === undefined) console.warn('forceClose: nothing to close on this node')","typeGuard":"function isOpen(ws: Workspace | undefined): ws is Workspace {\n  return ws !== undefined && ws.closing === undefined\n}","tryCatchPattern":"try {\n  await sessionManager.forceClose(wsId, currentSocket)\n} catch (err) {\n  logger.error('force-close failed', { wsId, err })\n} finally {\n  await verifyWorkspaceRebuildable(wsId) // ensure clients can reconnect afterwards\n}","preventionTips":["Only call forceClose as a last-resort admin action after normal close paths fail.","Track why force-close is needed per workspace; repeated force-closes indicate a systemic bug.","Pass ignoreSocket when the caller's own connection must survive the teardown.","Verify clients handle close code 99 and the TxModelUpgrade notification so they refresh and reconnect."],"tags":["force-close","workspace","sessions","lifecycle"],"backgroundTag":"workspace-force-close","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}