n8n-io/n8n · error · TypeORMError

Referenced column ${joinColumn.referencedColumnName} was not

Error message

Referenced column ${joinColumn.referencedColumnName} was not found in entity ${relation.inverseEntityMetadata.name}

What it means

Symmetric to the owning-side check, this resolves `inverseJoinColumns[].referencedColumnName` against `relation.inverseEntityMetadata.ownColumns` (note: ownColumns only, not embedded/inherited columns). If the referenced property is not found directly on the inverse entity, the junction cannot be built and TypeORM throws.

Source

Thrown at packages/@n8n/typeorm/src/metadata-builder/JunctionEntityMetadataBuilder.ts:261

	 * Collects inverse referenced columns from the given join column args.
	 */
	protected collectInverseReferencedColumns(
		relation: RelationMetadata,
		joinTable: JoinTableMetadataArgs,
	): ColumnMetadata[] {
		const hasInverseJoinColumns = !!joinTable.inverseJoinColumns;
		const hasAnyInverseReferencedColumnName = hasInverseJoinColumns
			? joinTable.inverseJoinColumns!.find((joinColumn) => !!joinColumn.referencedColumnName)
			: false;
		if (!hasInverseJoinColumns || (hasInverseJoinColumns && !hasAnyInverseReferencedColumnName)) {
			return relation.inverseEntityMetadata.primaryColumns;
		} else {
			return joinTable.inverseJoinColumns!.map((joinColumn) => {
				const referencedColumn = relation.inverseEntityMetadata.ownColumns.find(
					(column) => column.propertyName === joinColumn.referencedColumnName,
				);
				if (!referencedColumn)
					throw new TypeORMError(
						`Referenced column ${joinColumn.referencedColumnName} was not found in entity ${relation.inverseEntityMetadata.name}`,
					);

				return referencedColumn;
			});
		}
	}

	protected changeDuplicatedColumnNames(
		junctionColumns: ColumnMetadata[],
		inverseJunctionColumns: ColumnMetadata[],
	) {
		junctionColumns.forEach((junctionColumn) => {
			inverseJunctionColumns.forEach((inverseJunctionColumn) => {
				if (junctionColumn.givenDatabaseName === inverseJunctionColumn.givenDatabaseName) {
					const junctionColumnName =
						this.connection.namingStrategy.joinTableColumnDuplicationPrefix(
							junctionColumn.propertyName,

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Confirm `referencedColumnName` matches a column directly on the INVERSE entity (a @PrimaryColumn/@Column property, not one nested inside an @Embedded).
  2. Move the referenced column out of an embeddable onto the entity itself if you must reference it from a join table.
  3. Remove explicit `referencedColumnName` to default to the inverse entity's primary key.

Example fix

// before — 'slug' is not a top-level column on Tag
@JoinTable({
  joinColumn: { name: 'post_id', referencedColumnName: 'id' },
  inverseJoinColumn: { name: 'tag_id', referencedColumnName: 'slug' },
})

// after
@JoinTable({
  joinColumn: { name: 'post_id', referencedColumnName: 'id' },
  inverseJoinColumn: { name: 'tag_id', referencedColumnName: 'id' },
})
Defensive patterns

Strategy: validation

Validate before calling

for (const m of dataSource.entityMetadatas) {
  for (const r of m.manyToManyRelations) {
    if (!r.joinTable?.inverseJoinColumns) continue;
    const inverseOwn = r.inverseEntityMetadata.ownColumns.map(c => c.propertyName);
    for (const jc of r.joinTable.inverseJoinColumns) {
      if (jc.referencedColumnName && !inverseOwn.includes(jc.referencedColumnName)) {
        throw new Error(`inverseJoinColumn references unknown column ${jc.referencedColumnName} on ${r.inverseEntityMetadata.name}`);
      }
    }
  }
}

Try / catch

try { await dataSource.initialize(); } catch (e) { if (e instanceof TypeORMError && /Referenced column.*was not found in entity/) { /* inspect inverseJoinColumns + inverse entity ownColumns */ } throw e; }

Prevention

When it happens

Trigger: Declaring `@JoinTable({ inverseJoinColumn: { name: 'tag_id', referencedColumnName: 'slug' } })` where the inverse entity has no top-level `slug` property (it might be in a @Embedded column, or only on a different entity, or simply mistyped).

Common situations: The inverse entity uses an embedded primary key whose properties are not in `ownColumns`. Renaming the inverse entity's PK without updating the @JoinTable. Confusing the joinColumns vs inverseJoinColumns slots.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/bd8f7336cc45c520. Report an issue: GitHub.