different-ai/openwork · warning · EnterpriseMcpClientError

MCP_SHUTDOWN_FAILED

MCP_SHUTDOWN_FAILED

Error message

Enterprise MCP failed during ${phaseLabel[input.operationPhase]}${request}.

What it means

runConnectedOperation in packages/enterprise-mcp-client/src/enterprise-mcp-client.ts throws an EnterpriseMcpClientError with operationPhase "shutdown" and code MCP_SHUTDOWN_FAILED when closing the MCP session (session.client.close()) fails or exceeds closeTimeoutMs AND the operation itself did not already fail. The work may have succeeded; only teardown failed. Note the guard: if operationFailed is true, the shutdown error is swallowed so the original operation error propagates instead.

Solutions

  1. Increase closeTimeoutMs in createEnterpriseMcpClient options if closes are merely slow.
  2. Treat this as teardown-only: check whether the operation result was already obtained; retry the operation if its result is unknown.
  3. Inspect error.cause to distinguish a timeout ("did not close before its deadline") from a transport close rejection.
  4. Check server-side connection handling/timeouts; a server that kills sockets during close triggers this.

Example fix

// before
createEnterpriseMcpClient({ closeTimeoutMs: 500 })

// after
createEnterpriseMcpClient({ closeTimeoutMs: 10_000 })
Defensive patterns

Strategy: try-catch

Try / catch

try {
  result = await client.listTools(input)
} catch (error) {
  if (error instanceof EnterpriseMcpClientError && error.operationPhase === "shutdown") {
    // operation result unknown/lost to teardown: log cause, optionally retry
    console.warn("MCP session close failed:", error.cause)
  } else throw error
}

Prevention

When it happens

Trigger: listTools, callTool, listResources, readResource, or listResourceTemplates completes, but the finally-block close times out past closeTimeoutMs (default 5000ms) or the underlying transport's close() rejects (socket already destroyed, server hung up mid-close).

Common situations: Slow or half-dead server connections where the HTTP transport close hangs; very small configured closeTimeoutMs; network interruption right after a successful call; server that closes abruptly after responding.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/33057fa42afb8dcb. Report an issue: GitHub.

Appendix: source

Thrown at packages/enterprise-mcp-client/src/enterprise-mcp-client.ts:426

      operation: async (session) => {
        try {
          await connectWithProtocolNegotiation({
            session,
            connectionId: input.connection.id,
            operationPhase: input.operationPhase,
          })
          let operationFailed = false
          try {
            return await input.operation(session)
          } catch (error) {
            operationFailed = true
            throw error
          } finally {
            try {
              await closeWithinDeadline(() => session.client.close(), closeTimeoutMs)
            } catch (error) {
              if (!operationFailed) {
                throw new EnterpriseMcpClientError({
                  operationPhase: "shutdown",
                  requestPhase: session.observer.lastRequestPhase(),
                  cause: error,
                })
              }
            }
          }
        } catch (error) {
          await invalidateTerminallyRejectedCredential(session, {
            connectionId: input.connection.id,
            operationPhase: input.operationPhase,
          })
          throw error
        }
      },
    })
  }

View on GitHub (pinned to 2b7df46e8a)