{"record":{"id":"16fca543be0ce694","repo":"TryGhost/Ghost","slug":"entitytype-with-id-id-not-found-16fca5","errorCode":null,"errorMessage":"${entityType} with id ${id} not found","messagePattern":"(.+?) with id (.+?) not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"e2e/data-factory/persistence/adapters/knex.ts","lineNumber":58,"sourceCode":"    }\n\n    async deleteMany(entityType: string, ids: string[]): Promise<void> {\n        if (ids.length === 0) {\n            return;\n        }\n\n        await this.db(entityType)\n            .whereIn('id', ids)\n            .del();\n    }\n\n    async findById<T>(entityType: string, id: string): Promise<T> {\n        const result = await this.db(entityType)\n            .where('id', id)\n            .first();\n\n        if (!result) {\n            throw new Error(`${entityType} with id ${id} not found`);\n        }\n\n        return result;\n    }\n\n    async findMany<T>(entityType: string, query?: Record<string, unknown>): Promise<T[]> {\n        let queryBuilder = this.db(entityType);\n\n        if (query) {\n            queryBuilder = queryBuilder.where(query);\n        }\n\n        return await queryBuilder.select();\n    }\n}\n","sourceCodeStart":40,"sourceCodeEnd":74,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/e2e/data-factory/persistence/adapters/knex.ts#L40-L74","documentation":"Thrown by KnexPersistenceAdapter.findById() when no row matches the id in the table. Because insert() and update() both call findById() to return the resulting record, this error commonly surfaces as a follow-up: the row was written but can't be read back. Distinct from a query error — the query succeeded, the row just isn't there.","triggerScenarios":"After insert(): the row didn't actually persist (transaction rolled back, DB connection issue) or the id passed doesn't match what was inserted. After update(): the id never existed or the update's WHERE clause matched nothing. Direct findById(): querying a non-existent or already-deleted record.","commonSituations":"Knex adapter's insert wrote to a different table than expected (entityType mismatch); the id field in the data doesn't match the table's actual primary key column; a DB-level trigger rejected the insert silently; the row was deleted by another worker between insert and findById; MySQL strict mode rejected a column so the insert partially failed.","solutions":["Confirm entityType (table name) passed to insert matches the table findById queries — they must be the same string.","Verify the id generated in build() is actually being written (check the DB directly right after the insert throws).","Ensure the table's primary key column is named 'id' (the adapter hardcodes .where('id', id)).","Check for DB-level constraints/triggers that could reject the insert without throwing (strict-mode NOT NULL, etc.).","Rule out cross-worker interference by running the failing test in isolation (pnpm test path/to/test.ts)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify the row exists right after insert, with a clear assertion\nasync function insertAndVerify(adapter, entityType, data) {\n    const inserted = await adapter.insert(entityType, data);\n    const found = await adapter.findById(entityType, data.id);\n    if (!found) throw new Error(`Insert of ${entityType} silently failed — row not readable by id ${data.id}`);\n    return found;\n}","typeGuard":"function hasIdField(data) {\n    return data != null && data.id != null;\n}","tryCatchPattern":"try {\n    return await adapter.findById(entityType, id);\n} catch (err) {\n    if (/with id .* not found/i.test(err.message)) {\n        // distinguish post-insert-not-readable (likely a write problem) from a genuine lookup miss\n        console.error('Row not found after write — check table name, id column, and DB constraints:', err.message);\n    }\n    throw err;\n}","preventionTips":["Use the same entityType (table name) for insert and findById.","Ensure the table's primary key column is named 'id'.","Check DB strict-mode constraints that could silently reject inserts."],"tags":["e2e","data-factory","knex-adapter","mysql","not-found"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}