different-ai/openwork · error

Update MCP connection response was incomplete.

Error message

Update MCP connection response was incomplete.

What it means

The updateMcpConnection mutation in den-web always defines `updated` via a runReauthableAction callback that assigns the parsed response payload. If the callback body completes without assigning (e.g. the mutation helper swallowed the network call or an empty payload path left the variable undefined), this guard throws instead of returning a partially-typed object. It exists so the mutation never returns `null`/`undefined` typed as UpdatedMcpConnection.

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/mcp-connections-data.tsx:796

  const queryClient = useQueryClient();
  const { orgId, runReauthableAction } = useOrgDashboard();

  return useMutation({
    mutationFn: async (input: UpdateMcpConnectionInput): Promise<UpdatedMcpConnection> => {
      let updated: UpdatedMcpConnection | null = null;
      await runReauthableAction("update-mcp-connection", async () => {
        const { connectionId, ...body } = input;
        const { response, payload } = await requestJson(
          `/v1/mcp-connections/${encodeURIComponent(connectionId)}`,
          { method: "PUT", headers: getOrgScopeHeaders(requireOrgId(orgId)), body: JSON.stringify(body) },
          30000,
        );
        if (!response.ok) {
          throw getRequestError(payload, response, `Failed to update MCP connection (${response.status}).`);
        }
        updated = payload as UpdatedMcpConnection;
      });
      if (!updated) throw new Error("Update MCP connection response was incomplete.");
      return updated;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: mcpConnectionQueryKeys.all });
    },
  });
}

export function useReviewMcpIssuer() {
  const queryClient = useQueryClient();
  const { orgId, runReauthableAction } = useOrgDashboard();

  return useMutation({
    mutationFn: async (input: {
      connectionId: string;
      action: "preview" | "confirm";
      expectedUpdatedAt?: string;
      authorizationServerIssuer?: string;

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Log the payload inside the runReauthableAction callback to confirm the server response actually arrived and was assigned
  2. Verify the reauth wrapper (runReauthableAction) actually re-executes the callback on re-auth instead of resolving without it
  3. Check the update endpoint returns a JSON body on success, not 204/empty
  4. Re-test after re-signing-in to rule out a stale-token retry path

Example fix

// before
updated = payload as UpdatedMcpConnection;
});
if (!updated) throw new Error("Update MCP connection response was incomplete.");
// after
updated = payload as UpdatedMcpConnection;
});
if (!updated) {
  throw new Error(`Update MCP connection ${connectionId} returned no payload (status ${response.status}).`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

const canUpdate = typeof connectionId === 'string' && connectionId.length > 0 && typeof patch === 'object';

Type guard

function isUpdatedMcpConnection(v: unknown): v is UpdatedMcpConnection {
  return isRecord(v) && typeof (v as Record<string, unknown>).id === 'string';
}

Try / catch

try {
  await updateConnection.mutateAsync({ connectionId, patch });
} catch (e) {
  showToast({ variant: 'error', title: 'Could not update connection', description: e instanceof Error ? e.message : String(e) });
}

Prevention

When it happens

Trigger: mutateAsync on the update MCP connection mutation resolves but `updated` is still undefined: the runReauthableAction callback returned early, the response payload was never assigned (e.g. re-auth flow re-invoked the callback without reaching the assignment), or payload assignment was skipped after a silent auth retry.

Common situations: Session token expired mid-mutation so the reauth wrapper retried without re-running the body; a refactored callback introduced a code path that returns before `updated = payload ...`; API returns 2xx with empty body while code expected a JSON object.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


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