TryGhost/Ghost · error · Error
${entityType} with id ${id} not found
Error message
${entityType} with id ${id} not found What it means
Thrown by ApiPersistenceAdapter.findById() when the GET to {endpoint}/{id} returns HTTP 404. The entity with that id does not exist at the API. This is distinct from other non-ok statuses (handled by error 94) — a 404 is specifically 'not there', which the adapter surfaces with the entityType and id for easy identification.
Source
Thrown at e2e/data-factory/persistence/adapters/api.ts:58
const response = await this.httpClient.post(this.buildUrl(), {
data: this.transformRequest(data as unknown as TRequest)
});
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()) {View on GitHub (pinned to 47d8b0e2ad)
Solutions
- Confirm the id came from a successful create() (not a build(), which is in-memory only).
- Check whether a prior delete or another worker removed the entity — use per-test isolation if tests interfere.
- Verify the endpoint includes the correct resource path (a wrong baseURL/endpoint yields 404 even for valid ids).
- If the lookup is optional, catch the error and treat 404 as 'absent' rather than failing the test.
- Ensure 'pnpm dev' is serving the correct Ghost instance where the data was created.
Example fix
// before: assumes the post exists, throws on 404
const post = await apiAdapter.findById('posts', id);
// after: tolerate absence when the test expects it
let post;
try {
post = await apiAdapter.findById('posts', id);
} catch (err) {
if (/not found/.test(err.message)) post = null;
else throw err;
} Defensive patterns
Strategy: validation
Validate before calling
// Guard lookups you expect might miss
async function findOrNull(adapter, entityType, id) {
try {
return await adapter.findById(entityType, id);
} catch (err) {
if (/not found/.test(err.message)) return null;
throw err;
}
} Type guard
function isNotFoundMessage(msg) {
return /with id .* not found/i.test(msg);
} Try / catch
try {
const entity = await factory.findById(id);
} catch (err) {
if (isNotFoundMessage(err.message)) {
// expected absence — handle gracefully
} else throw err;
} Prevention
- Only look up ids returned from a successful create().
- Use per-test isolation when tests can delete each other's data.
- Remember build() is in-memory — its results are not findable via the adapter.
When it happens
Trigger: A test looks up an entity by id that was never created, was already deleted, or whose id is wrong. Also triggered internally by update() (which calls findById first) when attempting to update a non-existent record.
Common situations: Test ordered before the factory.create finished (race); the entity was deleted by a previous test step or another worker; id copied from a different environment; a factory build() generated an id that doesn't correspond to a persisted record (build is in-memory only).
Related errors
- Failed to create ${entityType}: ${response.status()} ${error
- Failed to update ${entityType}: ${response.status()}
- Cannot create without a persistence adapter. Use buildMany()
- Failed to find ${entityType}: ${response.status()}
- Failed to delete ${entityType}: ${response.status()}
AI-assisted analysis of TryGhost/Ghost@47d8b0e2ad (2026-08-13).
Data as JSON: /api/errors/5e1673d1e2df07bb.
Report an issue: GitHub.