hcengineering/platform · info

closing workspace, no users

Error message

closing workspace, no users

What it means

The SessionManager periodically ticks workspaces; if a workspace has zero sessions, has finished initialization, is not already closing, and its softShutdown countdown reaches zero, the manager logs this warning and starts a workspace close check (soft shutdown). This is normal garbage collection of idle workspaces, freeing memory.

Source

Thrown at foundations/server/packages/server/src/sessionManager.ts:323

      for (const s of workspace.sessions) {
        if (this.ticks % (5 * 60 * ticksPerSecond) === workspace.tickHash) {
          s[1].session.mins5.find = s[1].session.current.find
          s[1].session.mins5.tx = s[1].session.current.tx

          s[1].session.current = { find: 0, tx: 0 }
        }
      }

      // Wait some time for new client to appear before closing workspace.
      if (
        !workspace.maintenance &&
        workspace.sessions.size === 0 &&
        workspace.closing === undefined &&
        workspace.workspaceInitCompleted
      ) {
        workspace.softShutdown--
        if (workspace.softShutdown <= 0) {
          this.ctx.warn('closing workspace, no users', {
            workspace: workspace.wsId.url,
            wsId,
            upgrade: workspace.maintenance
          })
          workspace.closing = this.performWorkspaceCloseCheck(workspace)
        }
      } else {
        workspace.softShutdown = workspaceSoftShutdownTicks
      }
    }
  }

  private sendUserWorkspaceStats (): void {
    const { sys, user, anonymous } = this.calcWorkspaceStats(Array.from(this.sessions.values()))

    let userWorkspaces: number = 0
    let sysOnlyWorkspaces: number = 0

View on GitHub (pinned to 63e28dc964)

Solutions

  1. No action needed if workspaces are simply idle — they will be re-initialized on next connect
  2. If workspaces close too eagerly, increase the softShutdown timeout configuration
  3. If users report disconnects, check why sessions drop (network, ping timeouts) so the workspace never reaches zero sessions
  4. Monitor for repeated close/init cycles which would indicate a reconnect loop

Example fix

// before
softShutdown: 100 // ticks
// after (config, slower close of idle workspaces)
WORKSPACE_SOFT_SHUTDOWN_TICKS=1000
Defensive patterns

Strategy: try-catch

Validate before calling

const ws = await getWorkspace(ctx, workspaceId)
if (ws && ws.sessions.size > 0) console.log('workspace active; will not be closed by tick')

Type guard

function isIdleForClose(ws: { sessions: Set<unknown>; closing?: unknown; workspaceInitCompleted: boolean }): boolean {
  return ws.workspaceInitCompleted && ws.closing === undefined && ws.sessions.size === 0
}

Try / catch

try {
  await client.find(ctx, clazz, query, { workspaceId })
} catch (err) {
  if (isWorkspaceClosedError(err)) {
    await reconnectWorkspace(workspaceId) // triggers re-init
  } else throw err
}

Prevention

When it happens

Trigger: handleWorkspaceTick (from handleTick) sees workspace.sessions.size === 0 and softShutdown decrements to <= 0 — i.e. no user has been connected for the full softShutdown interval.

Common situations: Long-lived server accumulating idle workspaces; clients disconnecting and not reconnecting; test environments leaving workspaces open; misread as an error when it's expected lifecycle behavior.

Related errors


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