{"record":{"id":"9c16d70b9e360f49","repo":"n8n-io/n8n","slug":"internal-error-subject-subject-metadata-targetn","errorCode":null,"errorMessage":"Internal error. Subject ${subject.metadata.targetName} must have an identifier to perform operation.","messagePattern":"Internal error\\. Subject (.+?) must have an identifier to perform operation\\.","errorType":"exception","errorClass":"SubjectWithoutIdentifierError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/persistence/SubjectExecutor.ts","lineNumber":431,"sourceCode":"\t\t\t\t\t\tif (value !== undefined && value !== null) {\n\t\t\t\t\t\t\tconst preparedValue = this.queryRunner.connection.driver.prepareHydratedValue(\n\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\tcolumn,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tcolumn.setEntityValue(subject.generatedMap!, preparedValue);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Updates all given subjects in the database.\n\t */\n\tprotected async executeUpdateOperations(): Promise<void> {\n\t\tconst updateSubject = async (subject: Subject) => {\n\t\t\tif (!subject.identifier) throw new SubjectWithoutIdentifierError(subject);\n\n\t\t\tconst updateMap: ObjectLiteral = subject.createValueSetAndPopChangeMap();\n\n\t\t\t// for tree tables we execute additional queries\n\t\t\tswitch (subject.metadata.treeType) {\n\t\t\t\tcase 'nested-set':\n\t\t\t\t\tawait new NestedSetSubjectExecutor(this.queryRunner).update(subject);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'closure-table':\n\t\t\t\t\tawait new ClosureSubjectExecutor(this.queryRunner).update(subject);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'materialized-path':\n\t\t\t\t\tawait new MaterializedPathSubjectExecutor(this.queryRunner).update(subject);\n\t\t\t\t\tbreak;\n\t\t\t}\n","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/persistence/SubjectExecutor.ts#L413-L449","documentation":"Inside `executeUpdateOperations`, each update subject must carry an identifier (the primary-key map) so TypeORM can build `WHERE id = ...`. If `subject.identifier` is falsy it throws `SubjectWithoutIdentifierError`. The error's own docstring says this should never happen in normal use and is most likely an ORM-internal problem, but it surfaces when an update is attempted on an instance whose PK was never set.","triggerScenarios":"Calling `repository.update(entityInstance, ...)` or having cascade-update reach an entity instance whose primary key value is `undefined`/`null`. An entity with no `@PrimaryColumn`/`@PrimaryGeneratedColumn` being updated. Manually clearing the PK on a tracked entity before flush.","commonSituations":"Loading an entity, setting its id to undefined, then saving. A subclass/SINGLE_TABLE entity whose PK column isn't mapped. A bug in a custom subscriber that nulls the identifier.","solutions":["Ensure the entity instance has a non-null primary key before calling update/save (log `metadata.primaryColumns` values).","Confirm the entity class declares a `@PrimaryGeneratedColumn()` / `@PrimaryColumn()`.","If reached via cascade, reproduce with logging and report upstream — per the docs this path is considered an internal bug."],"exampleFix":"// before — id cleared, then update\nconst u = await repo.findOneBy({ id: 1 });\nu.id = undefined;\nawait repo.save(u); // throws inside executeUpdateOperations\n\n// after — keep the identifier\nconst u = await repo.findOneBy({ id: 1 });\nu.name = 'new';\nawait repo.save(u);","handlingStrategy":"validation","validationCode":"// Before update/save, confirm the instance carries a non-null primary key\nfunction hasId<T>(entity: T, meta: EntityMetadata): boolean {\n  return meta.primaryColumns.every(c => c.getEntityValue(entity) != null);\n}\nif (!hasId(entity, dataSource.getMetadata(EntityClass))) {\n  throw new Error('Cannot update: entity has no identifier');\n}","typeGuard":"function hasPrimaryKey<T>(e: T, pk: keyof T): e is T & Record<typeof pk, NonNullable<T[typeof pk]>> {\n  return e != null && (e as any)[pk] != null;\n}","tryCatchPattern":"try { await repo.save(entity); } catch (e) { if (e instanceof SubjectWithoutIdentifierError) { /* log PK columns; reload entity before update */ } throw e; }","preventionTips":["Never null out a primary key on a tracked entity before save.","Confirm every entity class declares a @PrimaryGeneratedColumn/@PrimaryColumn.","Update entities you loaded from the DB, not freshly-constructed copies."],"tags":["typeorm","persistence","primary-key","update","internal"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}