TryGhost/Ghost · error · Error
Failed to find ${entityType}: ${response.status()}
Error message
Failed to find ${entityType}: ${response.status()} What it means
Thrown by ApiPersistenceAdapter.findById() when the GET returns a non-ok, non-404 status — i.e. an auth failure (401/403), server error (500), or rate limit (429). The message includes the status code but not the body, so diagnosis leans on the numeric code. This fires for any findById failure that isn't a clean 404.
Source
Thrown at e2e/data-factory/persistence/adapters/api.ts:62
if (!response.ok()) {
const errorBody = await response.json().catch(() => null);
const errorMessage = errorBody ? JSON.stringify(errorBody) : '';
throw new Error(`Failed to create ${entityType}: ${response.status()} ${errorMessage}`);
}
const body = await response.json() as TResponse;
return this.transformResponse(body) as T;
}
async findById<T>(entityType: string, id: string): Promise<T> {
const response = await this.httpClient.get(this.buildUrl(id));
if (response.status() === 404) {
throw new Error(`${entityType} with id ${id} not found`);
}
if (!response.ok()) {
throw new Error(`Failed to find ${entityType}: ${response.status()}`);
}
const body = await response.json() as TResponse;
return this.transformResponse(body) as T;
}
async update<T>(entityType: string, id: string, data: Partial<T>): Promise<T> {
const existing = await this.findById<T>(entityType, id);
const response = await this.httpClient.put(this.buildUrl(id), {
data: this.transformRequest({...existing, ...data} as unknown as TRequest)
});
if (!response.ok()) {
throw new Error(`Failed to update ${entityType}: ${response.status()}`);
}
const body = await response.json() as TResponse;View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Act on the status code in the message: 401/403 → fix auth on the HTTP client; 500 → check Ghost server logs; 429 → reduce parallelism.
- Ensure the factory uses an authenticated page.request (session cookie from the fixture).
- Confirm 'pnpm dev' is healthy and the admin dev server is reachable.
- Verify the user role has read permission for the resource.
- Reduce worker count if the dev server is rate-limiting.
Defensive patterns
Strategy: try-catch
Validate before calling
// Probe auth/server health before depending on findById
async function endpointHealthy(httpClient, endpoint) {
const res = await httpClient.get(endpoint);
return res.ok() || res.status() === 404;
} Try / catch
try {
return await adapter.findById(entityType, id);
} catch (err) {
const status = /Failed to find .*: (\d+)/.exec(err.message)?.[1];
if (status === '401' || status === '403') throw new Error('Not authorized to read ' + entityType);
if (status === '500') throw new Error('Ghost server error reading ' + entityType + ' — check logs');
throw err;
} Prevention
- Use an authenticated admin HTTP client for all factory operations.
- Confirm 'pnpm dev' is healthy before the run.
- Limit worker parallelism if the dev server rate-limits (429).
When it happens
Trigger: The HTTP client isn't authenticated (401/403); the Ghost server errored (500); the request was rate-limited (429); the endpoint path is wrong and returns something other than 404; the dev server is mid-restart.
Common situations: Authentication cookie not propagated to the factory's HTTP client; Ghost dev server crashed or is restarting; an Admin API permission change made the resource unreadable by the test's role; concurrent workers overwhelming the dev server.
Related errors
- Failed to create ${entityType}: ${response.status()} ${error
- ${entityType} with id ${id} not found
- Failed to update ${entityType}: ${response.status()}
- Failed to delete ${entityType}: ${response.status()}
- Cannot create without a persistence adapter. Use buildMany()
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/6362fb34fbcf2be8.
Report an issue: GitHub.