n8n-io/n8n · error · TypeORMError

Unique constraint ${indexName}contains column that is missin

Error message

Unique constraint ${indexName}contains column that is missing in the entity (${entityName}): ${propertyName}

What it means

Thrown by UniqueMetadata.build when an @Unique constraint lists a property that is neither a column nor a join-column relation on the entity. The resolution mirrors IndexMetadata: find a column by propertyPath, then a join-column relation by propertyName; on failure it throws, naming the unique constraint (givenName) and the entity targetName.

Source

Thrown at packages/@n8n/typeorm/src/metadata/UniqueMetadata.ts:138

			}

			this.columns = columnPropertyPaths
				.map((propertyName) => {
					const columnWithSameName = this.entityMetadata.columns.find(
						(column) => column.propertyPath === propertyName,
					);
					if (columnWithSameName) {
						return [columnWithSameName];
					}
					const relationWithSameName = this.entityMetadata.relations.find(
						(relation) => relation.isWithJoinColumn && relation.propertyName === propertyName,
					);
					if (relationWithSameName) {
						return relationWithSameName.joinColumns;
					}
					const indexName = this.givenName ? '"' + this.givenName + '" ' : '';
					const entityName = this.entityMetadata.targetName;
					throw new TypeORMError(
						`Unique constraint ${indexName}contains column that is missing in the entity (${entityName}): ` +
							propertyName,
					);
				})
				.reduce((a, b) => a.concat(b));
		}

		this.columnNamesWithOrderingMap = Object.keys(map).reduce(
			(updatedMap, key) => {
				const column = this.entityMetadata.columns.find((column) => column.propertyPath === key);
				if (column) updatedMap[column.databasePath] = map[key];

				return updatedMap;
			},
			{} as { [key: string]: number },
		);

		this.name = this.givenName

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Cross-check each entry in the @Unique columns array against the entity's @Column and join-column relations.
  2. After renaming a column, update every @Unique referencing it.
  3. Remove the @Unique entry for any deleted column.

Example fix

// before
@Entity()
@Unique('uq_user_email', ['emial'])
export class User { @Column() email: string; }

// after
@Entity()
@Unique('uq_user_email', ['email'])
export class User { @Column() email: string; }
Defensive patterns

Strategy: validation

Validate before calling

function validateUniques(dataSource: DataSource): string[] {
  const problems: string[] = [];
  for (const meta of dataSource.entityMetadatas) {
    const cols = new Set(meta.columns.map((c) => c.propertyPath));
    const joinCols = new Set(
      meta.relations.filter((r) => r.isWithJoinColumn).map((r) => r.propertyName),
    );
    for (const uq of meta.uniques) {
      for (const givenPath of (uq.givenColumnNames as string[] | undefined) ?? []) {
        if (!cols.has(givenPath) && !joinCols.has(givenPath)) {
          problems.push(`${meta.targetName}.@Unique('${uq.givenName}') -> missing ${givenPath}`);
        }
      }
    }
  }
  return problems;
}

Try / catch

try {
  await dataSource.initialize();
} catch (err) {
  if (err.message.includes('Unique constraint') && err.message.includes('missing in the entity')) {
    // surface the unique-constraint/entity pair
  }
  throw err;
}

Prevention

When it happens

Trigger: Declaring @Unique('uq', ['missingField']) or @Unique(['missingField']) where the property is not a @Column or join-column relation.

Common situations: Typos in unique-constraint column arrays, dropping a column but leaving it in @Unique, pointing a unique constraint at a computed/getter property with no DB column.

Related errors


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