TryGhost/Ghost · error · Error
Timeout waiting for Ghost to become ready
Error message
Timeout waiting for Ghost to become ready
What it means
The readiness loop's overall timeout elapsed: the container is still running and not unhealthy, but probeHostReadiness() (fetch to /ghost/api/admin/authentication/setup through the gateway) never returned ok within the budget (default 120000ms, polled every READINESS_POLL_INTERVAL_MS). The manager dumps logs and throws. The container is slow to boot, not broken.
Source
Thrown at e2e/helpers/environment/service-managers/ghost-manager.ts:522
throw new Error('Ghost container became unhealthy during initialization');
}
if (!info.State.Running) {
const logs = await container.logs({stdout: true, stderr: true, tail: 100});
logging.error(`Container stopped unexpectedly:\n${logs.toString()}`);
throw new Error('Ghost container stopped during initialization');
}
// Still starting - wait and check again
await new Promise((r) => {
setTimeout(r, READINESS_POLL_INTERVAL_MS);
});
}
// Timeout
const logs = await container.logs({stdout: true, stderr: true, tail: 100});
logging.error(`Timeout waiting for container. Last logs:\n${logs.toString()}`);
throw new Error('Timeout waiting for Ghost to become ready');
}
private async probeHostReadiness(): Promise<boolean> {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 500);
try {
const response = await fetch(`http://localhost:${this.getGatewayPort()}/ghost/api/admin/authentication/setup`, {
method: 'GET',
headers: {Accept: 'application/json'},
signal: controller.signal
});
const body = await response.json().catch(() => null) as {setup?: Array<{status?: unknown}>} | null;
return response.ok && Array.isArray(body?.setup) && typeof body.setup[0]?.status === 'boolean';
} catch (error) {
debug('Host readiness probe failed:', error);
return false;View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Raise the timeout: call waitForReady(<larger ms>) or increase the default if the suite consistently needs more.
- Check the dumped logs — if migrations are running, pre-warm them or use a migrated seed image.
- Verify the gateway routes localhost:<getGatewayPort()> to the Ghost container; test the URL manually.
- Reduce concurrent worker count on the CI runner to lower boot contention.
Example fix
// before await ghostManager.waitForReady(); // default 120000ms // after await ghostManager.waitForReady(240000); // allow slow boots / migrations
Defensive patterns
Strategy: retry
Validate before calling
// Confirm the gateway path is reachable before the test runs:
const ok = await fetch(`http://localhost:${gatewayPort}/ghost/api/admin/authentication/setup`).then(r => r.ok).catch(() => false); Try / catch
try {
await ghostManager.waitForReady(120000);
} catch (e) {
// Retry once with a larger budget for slow boots / first-run migrations.
await ghostManager.waitForReady(240000);
} Prevention
- Scale the timeout to the slowest expected boot (cold migrations, loaded CI).
- Pre-warm migrations with a seeded DB image to shorten boot time.
- Reduce concurrent workers to lower boot contention on shared runners.
When it happens
Trigger: Ghost is genuinely slow to start (cold cache, slow migrations, slow DB). The gateway path is misrouted so the probe never reaches Ghost. Network/proxy overhead on the gateway port. Heavy CI machine under load.
Common situations: First-run DB migrations on a fresh schema; overloaded CI runner; gateway port forwarding broken; Ghost boot loop that hasn't yet tripped the healthcheck; tight default timeout on a slow arch.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Egress monitor sidecar did not start in time
- Build gateway image not found: ${BUILD_GATEWAY_IMAGE}\n\nTo
- Timeout after ${timeoutMs}ms waiting for search results
- Request timed out, please try again.
- Cannot create without a persistence adapter. Use buildMany()
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/e6ddd7bc7fbdcd5f.
Report an issue: GitHub.