tinyhumansai/openhuman · error · Error

mcp.health.opErrorGeneric

Error message

mcp.health.opErrorGeneric

What it means

Bulk reconnect from the MCP health toolbar: handleReconnectAll runs Promise.allSettled over mcpClientsApi.connect(id) for every selected server, always refreshes statuses so the health dots reflect reality, and only then throws the localized 'mcp.health.opErrorGeneric' if ANY individual connect rejected. Partial success is expected - the throw tells the toolbar 'not all succeeded' but carries no per-server detail.

Solutions

  1. Read the per-server status dots after the refresh - they were updated before the throw and show which servers actually failed
  2. Open the failing server's detail / reconnect it individually to get its real error message
  3. Fix or remove the dead entries (bad config, unreachable host) so bulk actions can go green
  4. If a transient network blip is suspected, run Reconnect-all again once

Example fix

// before - single generic error for any partial failure
if (results.some(r => r.status === 'rejected')) {
  throw new Error(t('mcp.health.opErrorGeneric'));
}

// after - keep the generic throw but include the failing ids for triage
const failed = results
  .map((r, i) => (r.status === 'rejected' ? serverIds[i] : null))
  .filter((id): id is string => id !== null);
if (failed.length > 0) {
  throw new Error(`${t('mcp.health.opErrorGeneric')} (${failed.join(', ')})`);
}
Defensive patterns

Strategy: fallback

Try / catch

// consume the bulk action knowing partial success is normal
try {
  await handleReconnectAll(serverIds);
} catch {
  // dots were refreshed before the throw - trust them, not this message
  await fetchStatuses();
  // reconnect failures individually to obtain their concrete errors
}

Prevention

When it happens

Trigger: Selecting multiple servers and clicking Reconnect-all where at least one connect(id) rejects - unreachable server, spawn failure, invalid transport config, or auth error on any member of the batch.

Common situations: Bulk-selecting a mixed set of healthy and dead servers; a dead server's rejection masking that the rest reconnected; treating the generic toolbar error as 'everything failed' when the dots show otherwise.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/3820b0ef6b5448a4. Report an issue: GitHub.

Appendix: source

Thrown at app/src/components/channels/mcp/McpServersTab.tsx:448

    void fetchCatalog(
      debouncedCatalogFilters.query,
      debouncedCatalogFilters.transport,
      catalogPage + 1,
      true
    );
  };

  // Bulk lifecycle actions for the health toolbar. One failure doesn't abort the
  // batch (allSettled), and we always refresh status so the dots reflect reality
  // — but if any call rejected we then throw so the toolbar can surface the
  // failure (otherwise a partial/total failure would look like success).
  const handleReconnectAll = useCallback(
    async (serverIds: string[]) => {
      log('reconnect all: %o', serverIds);
      const results = await Promise.allSettled(serverIds.map(id => mcpClientsApi.connect(id)));
      await fetchStatuses();
      if (results.some(r => r.status === 'rejected')) {
        throw new Error(t('mcp.health.opErrorGeneric'));
      }
    },
    [fetchStatuses, t]
  );

  const handleDisconnectAll = useCallback(
    async (serverIds: string[]) => {
      log('disconnect all: %o', serverIds);
      const results = await Promise.allSettled(serverIds.map(id => mcpClientsApi.disconnect(id)));
      await fetchStatuses();
      if (results.some(r => r.status === 'rejected')) {
        throw new Error(t('mcp.health.opErrorGeneric'));
      }
    },
    [fetchStatuses, t]
  );

  const selectedServer =

View on GitHub (pinned to 7491200858)