TryGhost/Ghost · error · Error
Timeout after ${timeoutMs}ms waiting for search results
Error message
Timeout after ${timeoutMs}ms waiting for search results What it means
Thrown by `MailPit.searchWithWait` when the polling loop exits the timeout window without matching messages. The loop polls Mailpit's search endpoint every 500ms until it finds any message (or exactly `numberOfMessages`); exhaustion means the expected email never arrived in the window.
Source
Thrown at e2e/helpers/services/email/mail-pit.ts:136
while (Date.now() - startTime < timeoutMs) {
const messages = await searchFn();
if (numberOfMessages === null) {
if (messages.length > 0) {
debug(`Found ${messages.length} messages`);
return messages;
}
} else {
if (messages.length === numberOfMessages) {
debug(`Found ${messages.length} messages`);
return messages;
}
}
await this.delay(500);
}
throw new Error(`Timeout after ${timeoutMs}ms waiting for search results`);
}
private async delay(milliseconds: number) {
await new Promise<void>((resolve) => {
setTimeout(resolve, milliseconds);
});
}
private async executeApiCall(endpoint: string, callType: string, method: string = 'GET'): Promise<Response> {
debug(`${callType} through ${endpoint}`);
const response = await fetch(`${this.apiUrl}/${endpoint}`, {method: method});
if (!response.ok) {
throw new Error(`Failed to ${callType}: ${response.statusText}`);
}
debug(`${callType} through ${endpoint} succeeded`);
return response;
}View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Increase `timeoutMs` for the search call in slow environments.
- Verify the search query parameters match how the email was actually sent (recipient address, subject).
- Confirm Ghost dispatched the email and Mailpit received it (check Mailpit UI/logs).
- Correct the expected `numberOfMessages` if the test assumption about email count is wrong.
Defensive patterns
Strategy: retry
Prevention
- Use a generous `timeoutMs` for email searches in slow environments.
- Match search query parameters exactly to how the email was addressed.
- Confirm Mailpit received the email (UI/logs) before assuming Ghost failed to send.
When it happens
Trigger: An email-dependent assertion waits for messages via `searchByRecipient`/`searchByQuery` with a timeout, and the condition (`messages.length > 0` or `=== numberOfMessages`) is never satisfied before `timeoutMs` elapses.
Common situations: Mailpit is slow to index; Ghost did not send the email; the recipient/search query does not match the sent mail; `numberOfMessages` expectation is wrong (too many/few); network latency between test runner and Mailpit.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- No staff invitation email found for ${email}
- No sign-in email found for ${member.email}
- Failed to ${callType}: ${response.statusText}
- email.error
- Egress monitor sidecar did not start in time
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/58942fdd63b31404.
Report an issue: GitHub.