hcengineering/platform · warning

FORCE CLOSE

Error message

FORCE CLOSE

What it means

TSessionManager logs 'FORCE CLOSE' when it receives a special RPC request (id === -2, method 'forceClose') for a workspace currently in maintenance mode; it then calls forceClose(workspaceId, ws) to evict sessions outside the normal interval handler (e.g. during upgrades). The TODO notes it should be restricted to admin/system accounts. Hitting this log means someone explicitly force-closed a maintenance-mode workspace over the protocol.

Source

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

          },
          service.binaryMode,
          service.useCompression
        )
        return
      }
      if (request.id === -1 && request.method === 'hello') {
        await requestCtx.with('🧨 handleHello', { source }, (ctx) =>
          this.handleHello<S>(request, service, ctx, workspace, ws, requestCtx)
        )
        return
      }
      if (request.id === -2 && request.method === 'forceClose') {
        // TODO: we chould allow this only for admin or system accounts
        let done = false
        const wsRef = this.workspaces.get(workspaceId)
        if (wsRef?.maintenance ?? false) {
          done = true
          this.ctx.warn('FORCE CLOSE', { workspace: workspaceId })
          // In case of upgrade, we need to force close workspace not in interval handler
          await this.forceClose(workspaceId, ws)
        }
        const forceCloseResponse: Response<any> = {
          id: request.id,
          result: done
        }
        await ws.send(requestCtx, forceCloseResponse, service.binaryMode, service.useCompression)
        return
      }
      let rateLimit: RateLimitInfo | undefined
      if (request.method !== 'ping') {
        rateLimit = this.checkRate(service)
        // If remaining is 0, rate limit is exceeded
        if (rateLimit?.remaining === 0) {
          service.updateLast()
          void ws.send(
            requestCtx,

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Expected during upgrades - no action; reconnect after maintenance ends.
  2. Implement the TODO access control: only allow forceClose for admin/system accounts before dispatching to forceClose().
  3. If forceClose fires unexpectedly, audit who can send request id -2 on your deployment.
  4. Ensure clients gracefully handle the forced disconnect (close frame / down event) and retry with backoff after maintenance.

Example fix

// before
if (request.id === -2 && request.method === 'forceClose') {
  let done = false
  const wsRef = this.workspaces.get(workspaceId)
  if (wsRef?.maintenance ?? false) {
    done = true
    this.ctx.warn('FORCE CLOSE', { workspace: workspaceId })
    await this.forceClose(workspaceId, ws)
  }
// after
if (request.id === -2 && request.method === 'forceClose') {
  if (!isAdminOrSystem(ctx)) return { id: request.id, result: false } // TODO enforced
  let done = false
  const wsRef = this.workspaces.get(workspaceId)
  if (wsRef?.maintenance ?? false) {
    done = true
    this.ctx.warn('FORCE CLOSE', { workspace: workspaceId })
    await this.forceClose(workspaceId, ws)
  }
Defensive patterns

Strategy: validation

Validate before calling

// Caller side: only send forceClose if maintenance is actually enabled
if (wsRef?.maintenance !== true) return // no forceClose needed
await sendRequest({ id: -2, method: 'forceClose' })

Type guard

function canForceClose (req: { id: number, method: string }, account: { role: string }): boolean {
  return req.id === -2 && req.method === 'forceClose' && (account.role === 'admin' || account.role === 'system')
}

Try / catch

try {
  const done = await sendRequest({ id: -2, method: 'forceClose' })
} catch (err) {
  console.error('forceClose failed', err) // workspace may lack maintenance flag
}

Prevention

When it happens

Trigger: A client (or tool) sends a JSON-RPC-style request with id -2 and method 'forceClose' targeting a workspaceId whose workspaces entry has maintenance === true.

Common situations: Platform upgrades putting workspaces into maintenance and then force-closing them; operators running admin scripts; misbehaving clients sending forceClose (currently unauthenticated - any account could trigger it per the TODO).

Related errors


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