typeorm/typeorm · error · TypeORMError

Relation "${entityTarget}#${relationPropertyPath}" does not

Error message

Relation "${entityTarget}#${relationPropertyPath}" does not have a many-to-many relationship.You can use this method only on many-to-many relations.

What it means

Thrown by DataSource.getManyToManyMetadata() when the resolved relation exists but `relationMetadata.isManyToMany` is false. The junction-table lookup only makes sense for many-to-many relations, so a @ManyToOne/@OneToMany/@OneToOne is rejected.

Source

Thrown at src/data-source/DataSource.ts:635

     * Gets entity metadata of the junction table (many-to-many table).
     *
     * @param entityTarget
     * @param relationPropertyPath
     */
    getManyToManyMetadata(
        entityTarget: EntityTarget<any>,
        relationPropertyPath: string,
    ) {
        const relationMetadata =
            this.getMetadata(entityTarget).findRelationWithPropertyPath(
                relationPropertyPath,
            )
        if (!relationMetadata)
            throw new TypeORMError(
                `Relation "${relationPropertyPath}" was not found in ${entityTarget} entity.`,
            )
        if (!relationMetadata.isManyToMany)
            throw new TypeORMError(
                `Relation "${entityTarget}#${relationPropertyPath}" does not have a many-to-many relationship.` +
                    `You can use this method only on many-to-many relations.`,
            )

        return relationMetadata.junctionEntityMetadata
    }

    /**
     * Creates an Entity Manager for the current connection with the help of the EntityManagerFactory.
     *
     * @param queryRunner
     */
    createEntityManager(queryRunner?: QueryRunner): EntityManager {
        return new EntityManagerFactory().create(this, queryRunner)
    }

    // -------------------------------------------------------------------------
    // Protected Methods

View on GitHub (pinned to 04ff4daedc)

Solutions

  1. Confirm the relation is decorated @ManyToMany; if not, use the appropriate metadata/repository API for its type.
  2. Switch the entity relation to @ManyToMany if a junction table is genuinely intended.
  3. Use getMetadata(...).relations to inspect the relation type before calling.

Example fix

// before
@Entity() class User { @ManyToOne(() => Dept) dept!: Dept }
ds.getManyToManyMetadata(User, 'dept') // throws

// after — use the relation as-is, not junction lookup
ds.getMetadata(User).findRelationWithPropertyPath('dept')
Defensive patterns

Strategy: validation

Validate before calling

const rel = dataSource.getMetadata(Entity).findRelationWithPropertyPath(path)
if (!rel || !rel.isManyToMany) {
  throw new Error(`Relation ${Entity.name}#${path} is not many-to-many`)
}
return dataSource.getManyToManyMetadata(Entity, path)

Type guard

function isManyToManyRelation(ds: DataSource, target: EntityTarget<any>, path: string): boolean {
  const r = ds.getMetadata(target).findRelationWithPropertyPath(path)
  return !!r && r.isManyToMany
}

Try / catch

try {
  return dataSource.getManyToManyMetadata(Entity, path)
} catch (e) {
  if (e instanceof TypeORMError && /many-to-many/.test(e.message)) { /* use non-junction API for this relation type */ throw e }
  else throw e
}

Prevention

When it happens

Trigger: Calling getManyToManyMetadata(Entity, prop) where prop is decorated with @ManyToOne, @OneToMany, or @OneToOne rather than @ManyToMany.

Common situations: Wrong API for the relation type (looking up a junction table that doesn't exist for non-M:N relations); refactoring a relation from M:N to M:1 without updating the metadata call.

Related errors


AI-assisted analysis of typeorm/typeorm@04ff4daedc (2026-08-03). Data as JSON: /data/errors/77f910196a4b08c9.json. Report an issue: GitHub.