n8n-io/n8n · critical · TypeORMError

Entity metadata for ${entityMetadata.name}#${relation.proper

Error message

Entity metadata for ${entityMetadata.name}#${relation.propertyPath} was not found. Check if you specified a correct entity object and if it's connected in the connection options.

What it means

Thrown in EntityMetadataBuilder.computeInverseEntitiesMap (the loop over entityMetadata.relations) when no registered entity metadata matches the relation's type. The matcher tries m.target === relation.type, then string fallback (targetName or givenTableName equal to relation.type). If none of the registered entity metadatas satisfies any branch, TypeORMError fires naming entityMetadata.name and relation.propertyPath.

Source

Thrown at packages/@n8n/typeorm/src/metadata-builder/EntityMetadataBuilder.ts:833

	}

	/**
	 * Computes entity metadata's relations inverse side properties.
	 */
	protected computeInverseProperties(
		entityMetadata: EntityMetadata,
		entityMetadatas: EntityMetadata[],
	) {
		entityMetadata.relations.forEach((relation) => {
			// compute inverse side (related) entity metadatas for all relation metadatas
			const inverseEntityMetadata = entityMetadatas.find(
				(m) =>
					m.target === relation.type ||
					(typeof relation.type === 'string' &&
						(m.targetName === relation.type || m.givenTableName === relation.type)),
			);
			if (!inverseEntityMetadata)
				throw new TypeORMError(
					'Entity metadata for ' +
						entityMetadata.name +
						'#' +
						relation.propertyPath +
						" was not found. Check if you specified a correct entity object and if it's connected in the connection options.",
				);

			relation.inverseEntityMetadata = inverseEntityMetadata;
			relation.inverseSidePropertyPath = relation.buildInverseSidePropertyPath();

			// and compute inverse relation and mark if it has such
			relation.inverseRelation = inverseEntityMetadata.relations.find(
				(foundRelation) => foundRelation.propertyPath === relation.inverseSidePropertyPath,
			);
		});
	}

	/**

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Add the missing entity to the DataSource entities array (or enable glob entity loading that includes it).
  2. If using arrow-function relation types, confirm the import resolves without a circular dependency (use string type or deferred import).
  3. For string-typed relations, ensure the value equals the target's targetName or givenTableName exactly.

Example fix

// before
@Entity()
export class Post {
  @ManyToOne(() => Author) // Author not in DataSource.entities
  author: Author;
}

// after
new DataSource({
  entities: [Post, Author], // register it
});
Defensive patterns

Strategy: validation

Validate before calling

function validateRelationTargets(
  entityClasses: Function[],
  dataSource: DataSource,
): string[] {
  const registered = new Set(
    dataSource.entityMetadatas.map((m) => (m.target as Function)?.name),
  );
  const problems: string[] = [];
  for (const cls of entityClasses) {
    const meta = dataSource.getMetadata(cls);
    for (const rel of meta.relations) {
      if (typeof rel.type === 'function') {
        const name = (rel.type as Function).name;
        if (!registered.has(name)) {
          problems.push(`${meta.targetName}.${rel.propertyPath} -> unregistered target ${name}`);
        }
      } else if (typeof rel.type === 'string') {
        const hit = dataSource.entityMetadatas.some(
          (m) => m.targetName === rel.type || m.givenTableName === rel.type,
        );
        if (!hit) problems.push(`${meta.targetName}.${rel.propertyPath} -> unregistered string target '${rel.type}'`);
      }
    }
  }
  return problems;
}

Try / catch

try {
  await dataSource.initialize();
} catch (err) {
  if (err.message.includes('Entity metadata for') && err.message.includes('was not found')) {
    // log the entity#relationPath pair and check DataSource.entities
  }
  throw err;
}

Prevention

When it happens

Trigger: Declaring @ManyToOne(() => MissingEntity) where MissingEntity is not in the DataSource entities list; using a string relation type that matches no targetName/givenTableName; circular import that resolves the relation function to undefined.

Common situations: Forgetting to register an entity in DataSource options (entities: [...]); broken import returning undefined due to a circular dependency; renaming an entity class without updating string relation types; tree-shaking stripping an entity.

Related errors


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