{"record":{"id":"8b2b9a1cc47296bb","repo":"influxdata/influxdb","slug":"cannot-delete-plugin-in-database-because-it-is-used-by","errorCode":null,"errorMessage":"Cannot delete plugin {} in database {} because it is used by trigger {}","messagePattern":"Cannot delete plugin (.+?) in database (.+?) because it is used by trigger (.+?)","errorType":"error_code","errorClass":"CatalogError","httpStatus":null,"severity":"error","filePath":"influxdb3_catalog/src/error.rs","lineNumber":229,"sourceCode":"    Other(#[from] anyhow::Error),\n\n    #[error(\n        \"Cannot overwrite Processing Engine Trigger {} in Database {}\",\n        trigger_name,\n        database_name\n    )]\n    ProcessingEngineTriggerExists {\n        database_name: String,\n        trigger_name: String,\n    },\n\n    #[error(\n        \"Cannot delete running plugin {}. Disable it first or use --force.\",\n        trigger_name\n    )]\n    ProcessingEngineTriggerRunning { trigger_name: String },\n\n    #[error(\n        \"Cannot delete plugin {} in database {} because it is used by trigger {}\",\n        plugin_name,\n        database_name,\n        trigger_name\n    )]\n    ProcessingEnginePluginInUse {\n        database_name: String,\n        plugin_name: String,\n        trigger_name: String,\n    },\n\n    #[error(\n        \"Processing Engine Plugin {} not in DB schema for {}\",\n        plugin_name,\n        database_name\n    )]\n    ProcessingEnginePluginNotFound {\n        plugin_name: String,","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_catalog/src/error.rs#L211-L247","documentation":"The plugin being deleted is still referenced by at least one Processing Engine trigger in the database. The catalog blocks the delete to prevent dangling triggers pointing at a missing plugin, reporting which trigger holds the reference.","triggerScenarios":"Calling the plugin delete API for plugin_name while any trigger in database_name still has plugin_name set as its plugin, e.g. trigger trigger_name.","commonSituations":"Removing a plugin package that was wired into one or more triggers; cleaning up after renaming plugins when old triggers still reference the old name; scripted teardown that deletes plugins before triggers.","solutions":["Delete or re-point the dependent trigger (DROP TRIGGER on trigger_name) before deleting the plugin.","Update the trigger to use a different plugin, then delete the old one.","Use --force if you accept leaving the trigger without its plugin (recreate the trigger afterwards)."],"exampleFix":"// before\ninfluxdb3 package delete my_plugin\n// after\ninfluxdb3 trigger delete my_trigger --database mydb\ninfluxdb3 package delete my_plugin","handlingStrategy":"validation","validationCode":"// Find and drop dependent triggers before deleting the plugin\nconst triggers = await client.listTriggers(db);\nfor (const t of triggers.filter(t => t.pluginName === pluginName)) {\n  await client.deleteTrigger(db, t.triggerName);\n}\nawait client.deletePlugin(db, pluginName);","typeGuard":"function hasDependentTriggers(triggers, pluginName) {\n  return Array.isArray(triggers) && triggers.some(t => t?.pluginName === pluginName);\n}","tryCatchPattern":"try {\n  await deletePlugin(db, pluginName);\n} catch (e) {\n  const m = String(e).match(/used by trigger (\\S+)/);\n  if (m) {\n    await deleteTrigger(db, m[1]);\n    await deletePlugin(db, pluginName);\n  } else throw e;\n}","preventionTips":["Treat plugin->trigger references as foreign keys: delete triggers first","List all triggers referencing a plugin before any cleanup","Rename plugins by creating the new trigger first, then removing the old pair together"],"tags":["processing-engine","plugin","trigger","referential-integrity"],"backgroundTag":"invalid-state-transition","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}