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
- Add the missing entity to the DataSource entities array (or enable glob entity loading that includes it).
- If using arrow-function relation types, confirm the import resolves without a circular dependency (use string type or deferred import).
- 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
- Register every entity (and every relation target) in the DataSource entities array; prefer an explicit list over fragile globbing.
- For circular imports, use arrow-function relation types so the import defers evaluation.
- Add a boot test that enumerates entityMetadatas and asserts every relation target is registered.
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
- Cannot find relation ${propertyPath}. Wrong relation specifi
- Cannot find relation ${propertyPath}. Wrong relation specifi
- Array initializations are not allowed in entity relations. P
- Azure Blob container name not configured. Please set `N8N_EX
- External storage bucket name not configured. Please set `N8N
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/ae9449220b1888f0.
Report an issue: GitHub.