{"record":{"id":"1aebd2dc32a565ae","repo":"different-ai/openwork","slug":"shutdown","errorCode":"SHUTDOWN","errorMessage":"Session DELETE returned HTTP ${deleteResponse.status}","messagePattern":"Session DELETE returned HTTP (.+?)","errorType":"exception","errorClass":"ProbeFailure","httpStatus":null,"severity":"error","filePath":"packages/enterprise-mcp-mock-server/src/testing/probe.ts","lineNumber":447,"sourceCode":"  let revocationClientSecret = options.credentials?.clientSecret ?? \"\"\n  let negotiatedProtocolHeader = \"\"\n  let revocationEndpoint: URL | null = null\n  const cleanup = async (requireValidDelete: boolean): Promise<void> => {\n    const cleanupDeadline = Date.now() + 2_000\n    if (sessionId && accessToken && negotiatedProtocolHeader) {\n      try {\n        const deleteResponse = await fetchStep(mcpUrl, {\n          method: \"DELETE\",\n          headers: {\n            authorization: `Bearer ${accessToken}`,\n            origin: baseUrl.origin,\n            \"mcp-session-id\": sessionId,\n            \"mcp-protocol-version\": negotiatedProtocolHeader,\n          },\n        }, \"SHUTDOWN\", cleanupDeadline)\n        await discardResponseBody(deleteResponse, \"SHUTDOWN\", \"mcp_session\")\n        if (requireValidDelete && deleteResponse.status !== 204) {\n          throw new ProbeFailure(\"SHUTDOWN\", \"mcp_session\", `Session DELETE returned HTTP ${deleteResponse.status}`)\n        }\n      } catch (error) {\n        if (requireValidDelete) throw error\n      }\n    }\n    if (revocationEndpoint && accessToken) {\n      try {\n        const revocationResponse = await fetchStep(revocationEndpoint, {\n          method: \"POST\",\n          headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n          body: new URLSearchParams({\n            token: accessToken,\n            client_id: revocationClientId,\n            ...(revocationClientSecret ? { client_secret: revocationClientSecret } : {}),\n          }),\n        }, \"SHUTDOWN\", cleanupDeadline)\n        await discardResponseBody(revocationResponse, \"SHUTDOWN\", \"oauth_token\")\n      } catch {","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/enterprise-mcp-mock-server/src/testing/probe.ts#L429-L465","documentation":"During cleanup the probe DELETEs the negotiated MCP session (expecting HTTP 204 per the MCP streamable-HTTP session lifecycle). When the caller set requireValidDelete (strict shutdown validation), any status other than 204 is raised as a SHUTDOWN ProbeFailure naming the actual status. With non-strict cleanup the DELETE failure is swallowed so it never masks a primary diagnostic failure.","triggerScenarios":"Running the probe in a mode where valid session teardown is required and the server responds to DELETE /<endpointPath> with mcp-session-id and Bearer token using a status like 200, 404 (session already gone), or 405 instead of 204.","commonSituations":"Targeting a non-conformant or older MCP server that returns 200 on session delete, a gateway/proxy stripping the DELETE or rewriting it, or a server that already expired the session so DELETE returns 404.","solutions":["Make the server return HTTP 204 with no body for authenticated session DELETE requests.","Check for middleware/proxies that intercept DELETE and return 405/200, and exempt the MCP endpoint.","If you do not need strict teardown conformance, run the probe in a mode that does not require a valid DELETE so cleanup failures are non-fatal.","Ensure the mcp-session-id header sent on DELETE matches the session established during initialize (no stale session reuse)."],"exampleFix":"// before (server route)\napp.delete(endpointPath, (req, res) => { sessions.delete(req.headers[\"mcp-session-id\"]); res.sendStatus(200) })\n// after\napp.delete(endpointPath, (req, res) => { sessions.delete(req.headers[\"mcp-session-id\"]); res.sendStatus(204) })","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const result = await probeEnterpriseMcpMockServer({ baseUrl, mode: \"fixture-conformance\" })\n} catch (e) {\n  if (e instanceof ProbeFailure && e.phase === \"SHUTDOWN\") {\n    // Session teardown issue; primary phases may still have passed.\n    console.warn(\"Non-fatal shutdown issue:\", e.message)\n  } else throw e\n}","preventionTips":["Make session DELETE handlers return exactly 204 with no body","Test session teardown (DELETE with mcp-session-id) in CI against your MCP server","Ensure proxies/middleware allow DELETE through to the MCP route","Never reuse or pre-expire sessions before the probe's cleanup runs"],"tags":["http","mcp","session-lifecycle","shutdown"],"backgroundTag":"unexpected-http-status-code","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}