{"record":{"id":"7fb6ccb33a14da59","repo":"TryGhost/Ghost","slug":"integration-not-found","errorCode":null,"errorMessage":"Integration not found.","messagePattern":"Integration not found\\.","errorType":"exception","errorClass":"NotFoundError","httpStatus":404,"severity":"error","filePath":"ghost/core/core/server/services/integrations/integrations-service.js","lineNumber":42,"sourceCode":"            }\n            try {\n                await this.ApiKeyModel.refreshSecret(model.toJSON(), Object.assign({}, options, {id: options.keyid}));\n\n                return await this.IntegrationModel.findOne({id: options.id}, {\n                    withRelated: ['api_keys', 'webhooks']\n                });\n            } catch (err) {\n                throw new InternalServerError({\n                    err: err\n                });\n            }\n        }\n\n        try {\n            return await this.IntegrationModel.edit(data, Object.assign(options, {require: true}));\n        } catch (error) {\n            if (error.message === 'NotFound' || error.message === 'EmptyResponse') {\n                throw new NotFoundError({\n                    message: tpl(messages.notFound, {\n                        resource: 'Integration'\n                    })\n                });\n            }\n\n            throw error;\n        }\n    }\n}\n\n/**\n * @returns {IntegrationsService} instance of the PostsService\n */\nconst getIntegrationsServiceInstance = ({IntegrationModel, ApiKeyModel}) => {\n    return new IntegrationsService({IntegrationModel, ApiKeyModel});\n};\n","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/ghost/core/core/server/services/integrations/integrations-service.js#L24-L60","documentation":"A NotFoundError from `IntegrationsService.edit` when editing without a `keyid` and `IntegrationModel.edit(..., {require: true})` rejects with a Bookshelf `NotFound`/`EmptyResponse` message. That means no integration row matched the edit's `id` filter, so Ghost translates the low-level error into a clean 404.","triggerScenarios":"PUT/PATCH to edit an integration whose `id` does not exist, was deleted, or is excluded by the caller's options filter (e.g. an ownership/scope filter that removes it). The `require: true` flag turns the silent empty update into a rejection that this catch maps to NotFoundError.","commonSituations":"The integration was deleted between page load and save; the id is wrong/truncated; the caller passes a webhook id or api-key id in the integration id field; an L10/scoped request filters out the integration so the edit matches nothing.","solutions":["Verify the integration still exists (`GET /integrations/{id}`) before editing.","Confirm you are sending the integration `id`, not a related api_key/webhook id.","Remove any filter in `options` that would exclude the integration from the edit query.","If it was deleted, re-create the integration instead of editing a stale id."],"exampleFix":"// before\nawait integrations.edit({name: 'x'}, {id: webhookId, require: true}); // wrong id -> 404\n\n// after\nconst integration = await integrations.findOne({id: integrationId});\nif (!integration) throw new Error('Integration missing');\nawait integrations.edit({name: 'x'}, {id: integrationId});","handlingStrategy":"validation","validationCode":"async function assertIntegrationExists(model, id, options = {}) {\n  const m = await model.findOne({id}, options);\n  if (!m) throw new Error(`Integration ${id} not found; it may have been deleted`);\n  return m;\n}","typeGuard":"const integrationExists = async (model, id, options) => Boolean(await model.findOne({id}, options));","tryCatchPattern":"try {\n  await integrations.edit(data, {id});\n} catch (err) {\n  if (err.type === 'NotFoundError' && /Integration not found/i.test(err.message)) refreshIntegrations();\n  else throw err;\n}","preventionTips":["GET the integration before editing to confirm it exists.","Send the integration id, not a webhook/api-key id.","Avoid options filters that exclude the target integration from the edit query."],"tags":["integrations","not-found","admin-api","crud"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}