{"record":{"id":"99c803bcb928b1ee","repo":"n8n-io/n8n","slug":"onupdatetype-relation-onupdate-is-not-valid-f","errorCode":null,"errorMessage":"OnUpdateType \"${relation.onUpdate}\" is not valid for ${driver.options.type}!","messagePattern":"OnUpdateType \"(.+?)\" is not valid for (.+?)!","errorType":"exception","errorClass":"TypeORMError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/metadata-builder/EntityMetadataValidator.ts","lineNumber":171,"sourceCode":"\t\tentityMetadata.relations.forEach((relation) => {\n\t\t\t// check OnDeleteTypes\n\t\t\tif (\n\t\t\t\tdriver.supportedOnDeleteTypes &&\n\t\t\t\trelation.onDelete &&\n\t\t\t\t!driver.supportedOnDeleteTypes.includes(relation.onDelete)\n\t\t\t) {\n\t\t\t\tthrow new TypeORMError(\n\t\t\t\t\t`OnDeleteType \"${relation.onDelete}\" is not supported for ${driver.options.type}!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// check OnUpdateTypes\n\t\t\tif (\n\t\t\t\tdriver.supportedOnUpdateTypes &&\n\t\t\t\trelation.onUpdate &&\n\t\t\t\t!driver.supportedOnUpdateTypes.includes(relation.onUpdate)\n\t\t\t) {\n\t\t\t\tthrow new TypeORMError(\n\t\t\t\t\t`OnUpdateType \"${relation.onUpdate}\" is not valid for ${driver.options.type}!`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// check join tables:\n\t\t\t// using JoinTable is possible only on one side of the many-to-many relation\n\t\t\t// todo(dima): fix\n\t\t\t// if (relation.joinTable) {\n\t\t\t//     if (!relation.isManyToMany)\n\t\t\t//         throw new UsingJoinTableIsNotAllowedError(entityMetadata, relation);\n\t\t\t//     // if there is inverse side of the relation, then check if it does not have join table too\n\t\t\t//     if (relation.hasInverseSide && relation.inverseRelation.joinTable)\n\t\t\t//         throw new UsingJoinTableOnlyOnOneSideAllowedError(entityMetadata, relation);\n\t\t\t// }\n\t\t\t// check join columns:\n\t\t\t// using JoinColumn is possible only on one side of the relation and on one-to-one, many-to-one relation types\n\t\t\t// first check if relation is one-to-one or many-to-one\n\t\t\t// todo(dima): fix","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/metadata-builder/EntityMetadataValidator.ts#L153-L189","documentation":"During entity metadata validation TypeORM cross-checks each relation's `onUpdate` referential action against the active driver's `supportedOnUpdateTypes` list. If the driver does not advertise the requested action the mapping is rejected outright rather than silently ignored, so an unsupported cascade cannot ship to the schema. This runs at schema-build time (DataSource.initialize / synchronize).","triggerScenarios":"Declaring `@ManyToOne(() => User, { onUpdate: 'CASCADE' })` (or any @OneToOne/@ManyToMany join column with `onUpdate`) while the DataSource is bound to SQLite, whose driver exposes an empty/limited `supportedOnUpdateTypes`. Also triggered by actions like 'SET NULL' or 'RESTRICT' on a driver that does not list them.","commonSituations":"Running Postgres locally with ON UPDATE cascades, then pointing CI at an in-memory sqlite3 DB. Upgrading the vendored typeorm to a version that tightened `supportedOnUpdateTypes`. Copying a relation decorator from a Postgres entity into a SQLite test entity.","solutions":["Drop `onUpdate` from the relation decorator and rely on the database default; this is the right call when targeting SQLite.","Match the DB engine: use Postgres/MySQL in the failing environment so the action is supported.","If you must keep the cascade, define it in a raw migration (`FOREIGN KEY ... ON UPDATE CASCADE`) instead of the decorator."],"exampleFix":"// before\n@ManyToOne(() => User, { onUpdate: 'CASCADE' })\nuser: User;\n\n// after\n@ManyToOne(() => User)\nuser: User;","handlingStrategy":"validation","validationCode":"// Before initializing, confirm the driver actually supports the onUpdate action\nconst supported = dataSource.driver.supportedOnUpdateTypes ?? [];\nconst want = 'CASCADE'; // the action declared in your decorator\nif (!supported.includes(want)) {\n  throw new Error(`Driver ${dataSource.options.type} does not support onUpdate='${want}'; supported: ${supported.join(',')}`);\n}","typeGuard":null,"tryCatchPattern":"try { await dataSource.initialize(); } catch (e) { if (e instanceof TypeORMError && /OnUpdateType/.test(e.message)) { /* surface a config-level message naming the driver + relation */ } throw e; }","preventionTips":["Run tests against the same DB engine you use in production; do not declare onUpdate cascades for SQLite-only tests.","Prefer default FK behavior and add ON UPDATE rules in explicit migrations you control.","Keep an inventory of which decorators use onUpdate/onDelete and review it when changing the DB driver."],"tags":["typeorm","relations","sqlite","schema-validation","foreign-keys"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}