linshenkx/prompt-optimizer · error
Health check failed
Error message
Health check failed
What it means
The /healthz route of the MCP server calls healthProvider.getHealthStatus(); if that promise rejects (or a non-Error is thrown), the catch block returns HTTP 503 with initialized:false and the error message, defaulting to the literal 'Health check failed' when the thrown value is not an Error instance.
Source
Thrown at packages/mcp-server/src/health.ts:29
export function buildHealthzResponse(healthStatus: MCPHealthStatus): {
statusCode: number;
body: MCPHealthStatus;
} {
return {
statusCode: isHealthyStatus(healthStatus) ? 200 : 503,
body: healthStatus
};
}
export function registerHealthzRoute(app: Express, healthProvider: HealthStatusProvider): void {
app.get('/healthz', async (_req, res) => {
try {
const healthStatus = await healthProvider.getHealthStatus();
const { statusCode, body } = buildHealthzResponse(healthStatus);
res.status(statusCode).json(body);
} catch (error) {
res.status(503).json({
initialized: false,
services: {},
error: error instanceof Error ? error.message : 'Health check failed'
});
}
});
}
View on GitHub (pinned to 3e677b1d9f)
Solutions
- Check the response body's error field and the server logs to see which underlying dependency failed (the generic message means a non-Error was thrown — log the raw value).
- Fix the underlying dependency (DB/storage connection, env config) so getHealthStatus resolves.
- Configure liveness/readiness probe thresholds to tolerate startup, or have getHealthStatus return degraded status objects instead of throwing.
Example fix
// before
res.status(503).json({ initialized: false, services: {}, error: error instanceof Error ? error.message : 'Health check failed' });
// after (also log the raw failure for diagnosis)
console.error('[healthz] non-Error failure:', error);
res.status(503).json({ initialized: false, services: {}, error: error instanceof Error ? error.message : String(error) }); Defensive patterns
Strategy: try-catch
Type guard
const isHealthzFailure = (body: unknown): body is { initialized: false; error: string } =>
typeof body === 'object' && body !== null && (body as any).initialized === false Try / catch
const res = await fetch(`${MCP_URL}/healthz`)
if (res.status === 503) {
const body = await res.json().catch(() => null)
log.warn('MCP unhealthy:', body?.error ?? 'unknown')
// retry with backoff; if the message is the generic 'Health check failed', a non-Error was thrown server-side
} Prevention
- Probe /healthz with retry/backoff at startup instead of assuming readiness.
- Ensure getHealthStatus returns status objects rather than throwing; wrap its internals in try/catch that returns degraded status.
- Configure orchestrator probes (k8s readiness) with appropriate initialDelaySeconds/failureThreshold.
When it happens
Trigger: GET /healthz while a dependency checked by getHealthStatus is down or throws — e.g. storage/DB unreachable, a service not yet initialized — or when getHealthStatus itself has a bug and throws a string/non-Error value (which surfaces as the generic message).
Common situations: Kubernetes/container probes hitting /healthz before dependencies are ready; misconfigured connection strings causing getHealthStatus to reject; version changes to the health provider API throwing TypeError instead of structured status.
Related errors
- Core services initialization failed: ${(error as Error).mess
- Failed to setup default model: ${(error as Error).message}
- Unsupported language: ${language}
- Prompt must be a non-empty string
- Template must be a non-empty string
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/416f78fe22e1edaa.
Report an issue: GitHub.