{"record":{"id":"bc682cc9463e325a","repo":"hcengineering/platform","slug":"workspace-closed","errorCode":null,"errorMessage":"Workspace closed...","messagePattern":"Workspace closed\\.\\.\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"foundations/server/packages/server/src/sessionManager.ts","lineNumber":1239,"sourceCode":"    }\n\n    if (LOGGING_ENABLED) {\n      this.ctx.warn('Clients disconnected. Closing Workspace...', {\n        url: workspace.wsId.url,\n        uuid: workspace.wsId.uuid\n      })\n    }\n\n    sessions\n      .filter((it) => it[1].socket.id !== ignoreSocket?.id)\n      .forEach((s) => {\n        closeS(s[1].session, s[1].socket)\n      })\n\n    if (reason !== 'upgrade') {\n      await workspace.close(this.ctx)\n      if (LOGGING_ENABLED) {\n        this.ctx.warn('Workspace closed...', { uuid: workspace.wsId.uuid, url: workspace.wsId.url })\n      }\n    }\n  }\n\n  private sendUpgrade (ctx: MeasureContext, webSocket: ConnectionSocket, binary: boolean, compression: boolean): void {\n    void webSocket.send(\n      ctx,\n      {\n        result: {\n          _class: core.class.TxModelUpgrade\n        }\n      },\n      binary,\n      compression\n    )\n  }\n\n  async closeWorkspaces (ctx: MeasureContext): Promise<void> {","sourceCodeStart":1221,"sourceCodeEnd":1257,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/server/src/sessionManager.ts#L1221-L1257","documentation":"Warning logged at the end of doCloseAll (guarded by LOGGING_ENABLED) after workspace.close(this.ctx) completed, for every close reason except 'upgrade' (where the workspace object stays alive for the upgrade handoff). It confirms the workspace was fully closed and its resources released on this node.","triggerScenarios":"doCloseAll finished with reason !== 'upgrade' ('shutdown' or 'force-close'), workspace.close() resolved successfully, and LOGGING_ENABLED is true. Not emitted for upgrade closes because the workspace persists through the model upgrade.","commonSituations":"Node shutdown finalizing workspace teardown; force-close completing on a stuck workspace; monitoring confirming workspace lifecycle completion.","solutions":["Expected terminal log — no action needed when it follows a deliberate shutdown or force-close.","If it appears without an operator action, check for automated force-close or shutdown triggers and the callers of doCloseAll.","If the preceding workspace.close() threw, the log is skipped — investigate close errors rather than this entry."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const closed = await sessionManager.forceClose(wsId)\nconst stillOpen = sessionManager.workspaces.get(wsId)\nif (stillOpen !== undefined) console.error('workspace not fully closed', { wsId })","typeGuard":"function isClosed(ws: Workspace | undefined): boolean {\n  return ws === undefined || ws.closing !== undefined\n}","tryCatchPattern":"try {\n  await sessionManager.forceClose(wsId)\n} catch (err) {\n  logger.error('workspace close failed before completion', { wsId, err })\n}","preventionTips":["Treat this log as the success marker for workspace teardown in operational runbooks.","After shutdown or force-close, verify the workspace registry no longer routes to this node.","Monitor for workspaces that get disconnects (1118) but never the closed confirmation — indicates a hung workspace.close().","Keep LOGGING_ENABLED on for lifecycle auditing."],"tags":["workspace","shutdown","lifecycle","logging"],"backgroundTag":"workspace-closed","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}