DIYgod/RSSHub · error · Error
Fortnite API responded with ${statusMessage} for ${apiUrl}
Error message
Fortnite API responded with ${statusMessage} for ${apiUrl} What it means
After Playwright successfully receives a response, response.ok() is checked — it returns false for any HTTP status outside the 200–299 range. The Fortnite API returning a 4xx/5xx means the endpoint rejected the request (rate limited, unauthorized, not found, or server error). The status code and status text are joined into a single descriptive message.
Source
Thrown at lib/routes/fortnite/news.ts:65
await page.route('**/*', (route) => {
const request = route.request();
request.resourceType() === 'document' ? route.continue() : route.abort();
});
// log manually (necessary for Playwright)
logger.http(`Requesting ${apiUrl}`);
let data;
try {
const response = await page.goto(apiUrl, {
waitUntil: 'networkidle',
});
if (!response) {
throw new Error(`No response received from ${apiUrl}`);
}
if (!response.ok()) {
const statusText = response.statusText();
const statusMessage = [response.status(), statusText].filter(Boolean).join(' ');
throw new Error(`Fortnite API responded with ${statusMessage} for ${apiUrl}`);
}
const contentType = response.headers()['content-type'];
if (!contentType?.includes('application/json')) {
throw new Error(`Fortnite API returned non-JSON response with content-type ${contentType ?? 'unknown'}`);
}
data = await response.json();
} finally {
await page.close();
await context.close();
}
const { blogList: list } = data;
const items = await Promise.all(
list.map((item) =>
cache.tryGet(item.link, () =>
Promise.resolve({View on GitHub (pinned to bed535e087)
Solutions
- Check the numeric status in the message: 401/403 → auth/cookie issue, 404 → endpoint moved, 429 → rate limit, 5xx → upstream outage.
- Ensure the Playwright browser context is shared and not isolated per request so session cookies persist.
- Add the Fortnite API host to the allowed request types in the interceptor so auth/XHR subrequests succeed.
- Report or update the apiUrl if Epic changed the endpoint.
Example fix
// before
if (!response.ok()) {
const statusText = response.statusText();
const statusMessage = [response.status(), statusText].filter(Boolean).join(' ');
throw new Error(`Fortnite API responded with ${statusMessage} for ${apiUrl}`);
}
// after
if (!response.ok()) {
const statusText = response.statusText();
const statusMessage = [response.status(), statusText].filter(Boolean).join(' ');
if (response.status() === 429) {
throw new Error(`Fortnite API rate-limited the request (429). Reduce request frequency.`);
}
throw new Error(`Fortnite API responded with ${statusMessage} for ${apiUrl}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// cannot pre-validate a server-side status; pre-flight with a HEAD request
import ofetch from '@/utils/ofetch';
try {
await ofetch.raw(apiUrl, { method: 'HEAD' });
} catch (e) { /* expect non-2xx, log for visibility */ } Type guard
const isRateLimited = (status: number) => status === 429;
Try / catch
try {
// ... page.goto + ok() check
} catch (e) {
if (/429/.test((e as Error).message)) {
await new Promise((r) => setTimeout(r, 5000)); // back off
}
throw e;
} Prevention
- Reuse a persistent browser context so session cookies/auth persist.
- Back off on 429 responses.
- Monitor Epic Games status for outages causing 5xx.
When it happens
Trigger: Fortnite's API returns 401/403 when the request lacks required cookies or headers (Playwright must have completed the auth flow), 404 when the endpoint path changed, 429 when rate limited, or 5xx during an Epic Games outage. Because the route loads the API URL as a browser document, missing browser-side auth tokens cause 401/403.
Common situations: Epic Games rotating the API URL or adding new required query parameters; the Playwright context not retaining session cookies; hitting the API too frequently and triggering rate limits; regional blocks returning 451.
Related errors
- Bilibili browser mode returned unexpected video list API sta
- HTTP error! status: ${res.status}
- Baidu security verification required. The cookie may be expi
- Bilibili browser mode did not receive a video list response
- Bilibili browser mode returned non-JSON response with status
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/dcfa044593c30634.
Report an issue: GitHub.