{"record":{"id":"c021238631160fcd","repo":"paperclipai/paperclip","slug":"plugin-migrations-may-contain-ddl-or-namespace-sco","errorCode":null,"errorMessage":"Plugin migrations may contain DDL or namespace-scoped backfill statements only","messagePattern":"Plugin migrations may contain DDL or namespace-scoped backfill statements only","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/plugin-database.ts","lineNumber":212,"sourceCode":"): void {\n  assertIdentifier(namespace, \"namespace\");\n  assertNoBannedSql(statement);\n\n  const normalized = normaliseSql(statement);\n  if (/^\\s*(drop|truncate)\\b/.test(normalized)) {\n    throw new Error(\"Destructive plugin migrations are not allowed in Phase 1\");\n  }\n\n  if (/\\bdelete\\s+from\\b/.test(normalized)) {\n    throw new Error(\"Plugin migrations cannot delete data\");\n  }\n\n  const ddlOrBackfillAllowed =\n    /^(create|alter|comment)\\b/.test(normalized) ||\n    /^(insert\\s+into|update)\\b/.test(normalized) ||\n    (normalized.startsWith(\"with \") && /\\b(insert\\s+into|update)\\b/.test(normalized));\n  if (!ddlOrBackfillAllowed) {\n    throw new Error(\"Plugin migrations may contain DDL or namespace-scoped backfill statements only\");\n  }\n\n  const refs = extractQualifiedRefs(statement);\n  if (refs.length === 0 && !normalized.startsWith(\"comment \")) {\n    throw new Error(\"Plugin migration objects must use fully qualified schema names\");\n  }\n\n  const objectRefKeywords = new Set([\n    \"alter table\",\n    \"create index\",\n    \"create table\",\n    \"create view\",\n    \"drop table\",\n    \"into\",\n    \"truncate table\",\n    \"update\",\n  ]);\n  const hasQualifiedObjectRef = refs.some((ref) => objectRefKeywords.has(ref.keyword));","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/paperclipai/paperclip/blob/120ae5428fa29bee300bcf806491cd4d965fbb7c/server/src/services/plugin-database.ts#L194-L230","documentation":"Statement-shape guard in validatePluginMigrationStatement: the statement is not DDL (create/alter/comment), not a backfill (insert into/update), and not a CTE ending in insert/update. Arbitrary statement types (e.g. raw select scripts, pragma, transactions) are rejected so migration effects stay predictable; the off-spec migration statement is at fault.","triggerScenarios":"Thrown at server/src/services/plugin-database.ts:212 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Restrict the migration to DDL or namespace-scoped backfill statements only."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"120ae5428fa29bee300bcf806491cd4d965fbb7c","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}