Skip to content

fix(mcp): coerce corrupted consecutiveFailures instead of crashing the whole server list#5593

Merged
waleedlatif1 merged 1 commit into
stagingfrom
worktree-fix-mcp-status-config-nan
Jul 11, 2026
Merged

fix(mcp): coerce corrupted consecutiveFailures instead of crashing the whole server list#5593
waleedlatif1 merged 1 commit into
stagingfrom
worktree-fix-mcp-status-config-nan

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Active production incident: 81 MCP servers across 69 workspaces currently have their entire "MCP tools" settings page blanked with "Response failed contract validation" — confirmed via direct DB query against the production database
  • Root cause: updateServerStatus() in lib/mcp/service.ts only fell back to a default status config when the whole statusConfig column was null, not when it was a real-but-incomplete object (e.g. the column's '{}' default on server creation). This made consecutiveFailures undefined, undefined + 1 evaluate to NaN, and JSON.stringify(NaN) persist as a literal null the first time a freshly-created server hit a connection failure
  • That corrupted null then failed the server-list contract's Zod parse client-side (consecutiveFailures: z.number() rejects null) — since the response is an array, one bad server blanks the entire list for the whole workspace
  • Fixed in two places: service.ts now normalizes the read-back status config so consecutiveFailures is always a real number going forward; the contract schema also coerces any non-number consecutiveFailures (including already-corrupted null rows) to the default of 0, so all 69 currently-broken workspaces self-heal immediately on next page load — no DB migration needed

Type of Change

  • Bug fix (production incident)

Testing

  • Verified the fix against the exact corrupted production data shape with a standalone Zod parse script ({consecutiveFailures: null}{consecutiveFailures: 0, ...}, no longer throws)
  • Existing lib/mcp/service.test.ts suite passes (11/11)
  • bun run check:api-validation passes

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…e whole server list

Root cause: updateServerStatus() only fell back to the default status
config when the whole statusConfig column was null/undefined, not when
it was a real object missing consecutiveFailures (e.g. the column's
'{}' default on server creation). currentConfig.consecutiveFailures
was then undefined, undefined + 1 evaluated to NaN, and
JSON.stringify(NaN) persisted as a literal `null` into the DB the
first time a freshly-created server had a connection failure.

That corrupted value then failed listMcpServersContract's Zod parse
client-side (consecutiveFailures: z.number() rejects null), and since
the response is a single array, one bad server blanked the entire MCP
servers list with "Response failed contract validation" for the whole
workspace — currently affecting 81 servers across 69 production
workspaces.

Two fixes:
- service.ts: normalize the read-back statusConfig so
  consecutiveFailures is always a real number, never NaN, going
  forward.
- contracts/mcp.ts: coerce any non-number consecutiveFailures
  (including the already-corrupted `null` rows) to the schema's
  default of 0 instead of failing validation, so every
  already-affected workspace self-heals on next load with no DB
  migration needed.
@vercel

vercel Bot commented Jul 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 11, 2026 5:33pm

Request Review

@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches MCP connection status persistence and list API validation for a user-facing settings surface; changes are narrow and defensive with low blast radius beyond healing corrupt rows.

Overview
Fixes a production bug where one MCP server with a bad statusConfig could make the entire workspace MCP server list fail contract validation and render blank.

updateServerStatus now builds currentConfig from partial stored JSON so consecutiveFailures is always a number before + 1, preventing NaN / null from being written when new servers (e.g. default {} config) hit their first failure.

The MCP server list contract preprocesses consecutiveFailures so any non-number (including already-corrupted null) defaults to 0, so existing bad rows self-heal on the next list load without a migration.

Reviewed by Cursor Bugbot for commit 95f9625. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes MCP server status parsing tolerate corrupted failure counts. The main changes are:

  • Adds a schema preprocess for consecutiveFailures.
  • Defaults non-number failure counts to 0 during contract parsing.
  • Normalizes partial persisted statusConfig before updating server status.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.
  • The update path now handles the empty-object and null failure-count cases described in the incident.

Important Files Changed

Filename Overview
apps/sim/lib/api/contracts/mcp.ts Adds defensive parsing for corrupted consecutiveFailures values in the MCP server status contract.
apps/sim/lib/mcp/service.ts Builds a normalized status config before incrementing or resetting MCP server failure counts.

Reviews (1): Last reviewed commit: "fix(mcp): coerce corrupted consecutiveFa..." | Re-trigger Greptile

@waleedlatif1 waleedlatif1 merged commit 3d02bbb into staging Jul 11, 2026
18 checks passed
@waleedlatif1 waleedlatif1 deleted the worktree-fix-mcp-status-config-nan branch July 11, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant