TryGhost/Ghost · error · Error

Failed to ${callType}: ${response.statusText}

Error message

Failed to ${callType}: ${response.statusText}

What it means

Thrown by `MailPit.executeApiCall` when a `fetch` to the Mailpit API returns a non-OK HTTP status. It surfaces the call type and `response.statusText` so the caller knows which operation failed and why. This is the lower-level transport guard beneath all Mailpit search/message operations.

Source

Thrown at e2e/helpers/services/email/mail-pit.ts:149

            }

            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;
    }

    private async parseMessagesFromResponse(response: Response): Promise<EmailMessage[]> {
        const data = await response.json() as EmailMessageSearchResult;
        debug(`Found ${data.count} messages`);
        return data.messages;
    }
}

View on GitHub (pinned to 47d8b0e2ad)

Solutions

  1. Verify Mailpit is reachable at `this.apiUrl` (curl the base URL).
  2. Check the failing endpoint and query string for malformed/over-encoded characters.
  3. Inspect Mailpit container logs for the 4xx/5xx root cause.
  4. Ensure the Mailpit API version matches the endpoints the helper calls.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    const messages = await emailClient.searchByRecipient(recipient, {timeoutMs});
} catch (err) {
    if (/Failed to .*:/.test(String((err as Error).message))) {
        // Mailpit transport error — check connectivity before failing the test
        throw new Error(`Mailpit API unreachable: ${(err as Error).message}`);
    }
    throw err;
}

Prevention

When it happens

Trigger: Any Mailpit API call (search messages, get message detail) returns a 4xx/5xx — e.g., Mailpit not running at `apiUrl`, wrong endpoint path, malformed query string producing 400, or Mailpit returning 500 under load.

Common situations: Mailpit container is down or not started yet; `apiUrl` is misconfigured; the encoded search query contains illegal characters producing a 400; Mailpit version mismatch changing endpoint paths; resource exhaustion causing 500s.

Related errors


AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13). Data as JSON: /api/errors/562f3af4a37a0486. Report an issue: GitHub.