{"record":{"id":"562f3af4a37a0486","repo":"TryGhost/Ghost","slug":"failed-to-calltype-response-statustext","errorCode":null,"errorMessage":"Failed to ${callType}: ${response.statusText}","messagePattern":"Failed to (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"e2e/helpers/services/email/mail-pit.ts","lineNumber":149,"sourceCode":"            }\n\n            await this.delay(500);\n        }\n\n        throw new Error(`Timeout after ${timeoutMs}ms waiting for search results`);\n    }\n\n    private async delay(milliseconds: number) {\n        await new Promise<void>((resolve) => {\n            setTimeout(resolve, milliseconds);\n        });\n    }\n\n    private async executeApiCall(endpoint: string, callType: string, method: string = 'GET'): Promise<Response> {\n        debug(`${callType} through ${endpoint}`);\n        const response = await fetch(`${this.apiUrl}/${endpoint}`, {method: method});\n        if (!response.ok) {\n            throw new Error(`Failed to ${callType}: ${response.statusText}`);\n        }\n\n        debug(`${callType} through ${endpoint} succeeded`);\n        return response;\n    }\n\n    private async parseMessagesFromResponse(response: Response): Promise<EmailMessage[]> {\n        const data = await response.json() as EmailMessageSearchResult;\n        debug(`Found ${data.count} messages`);\n        return data.messages;\n    }\n}\n","sourceCodeStart":131,"sourceCodeEnd":162,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/e2e/helpers/services/email/mail-pit.ts#L131-L162","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify Mailpit is reachable at `this.apiUrl` (curl the base URL).","Check the failing endpoint and query string for malformed/over-encoded characters.","Inspect Mailpit container logs for the 4xx/5xx root cause.","Ensure the Mailpit API version matches the endpoints the helper calls."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    const messages = await emailClient.searchByRecipient(recipient, {timeoutMs});\n} catch (err) {\n    if (/Failed to .*:/.test(String((err as Error).message))) {\n        // Mailpit transport error — check connectivity before failing the test\n        throw new Error(`Mailpit API unreachable: ${(err as Error).message}`);\n    }\n    throw err;\n}","preventionTips":["Verify Mailpit is reachable at the configured `apiUrl` before running tests.","Ensure the search query string is correctly encoded to avoid 400s.","Match the Mailpit API version to the endpoints the helper calls."],"tags":["email","e2e","mailpit","http","network"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}