drizzle-team/drizzle-orm · error · Error
There is not enough information to infer relation "${sourceT
Error message
There is not enough information to infer relation "${sourceTableTsName}.${relation.fieldName}" What it means
normalizeRelation() throws when it cannot infer the foreign-key fields for a relation. This happens when a relation is a many() (which carries no field info) and there is no matching one() on the other side whose fields/references can be mirrored, or when the one() on the other side also lacks config. Drizzle infers a many()'s fields by finding the reverse one(); if none exists or it has no config, inference fails.
Source
Thrown at drizzle-orm/src/relations.ts:631
: new Error(
`There are multiple relations between "${referencedTableTsName}" and "${
relation.sourceTable[Table.Symbol.Name]
}". Please specify relation name`,
);
}
if (
reverseRelations[0]
&& is(reverseRelations[0], One)
&& reverseRelations[0].config
) {
return {
fields: reverseRelations[0].config.references,
references: reverseRelations[0].config.fields,
};
}
throw new Error(
`There is not enough information to infer relation "${sourceTableTsName}.${relation.fieldName}"`,
);
}
export function createTableRelationsHelpers<TTableName extends string>(
sourceTable: AnyTable<{ name: TTableName }>,
) {
return {
one: createOne<TTableName>(sourceTable),
many: createMany(sourceTable),
};
}
export type TableRelationsHelpers<TTableName extends string> = ReturnType<
typeof createTableRelationsHelpers<TTableName>
>;
export interface BuildRelationalQueryResult<View on GitHub (pinned to b7862528fd)
Solutions
- Add the reverse one() relation on the target table with explicit fields and references: relations(posts, ({ one }) => ({ author: one(users, { fields: [posts.authorId], references: [users.id] }) })).
- If both sides are one() (e.g., 1:1), add a relationName to disambiguate and ensure at least one side declares fields/references.
- Verify the relation field name matches what you query and that the foreign-key column actually exists.
Example fix
// before (only many() side, no reverse one() -> cannot infer)
export const userRelations = relations(users, ({ many }) => ({
posts: many(postRelations),
}));
export const postRelations = relations(posts, () => ({})); // missing reverse
// after
export const postRelations = relations(posts, ({ one }) => ({
author: one(users, { fields: [posts.authorId], references: [users.id] }),
})); Defensive patterns
Strategy: validation
Validate before calling
// Validate every many() has a reverse one() with fields/references.
import { Table } from 'drizzle-orm/table';
import { is } from 'drizzle-orm/entity';
import { One, Relations } from 'drizzle-orm/relations';
function validateManyHasReverseOne(schema: Record<string, any>) {
const onesByPair = new Map<string, boolean>();
for (const v of Object.values(schema)) {
if (!is(v, Relations)) continue;
for (const r of Object.values((v as any).config)) {
if (is(r, One)) {
const key = [(v as any).table[Table.Symbol.Name], r.referencedTable[Table.Symbol.Name]].join('->');
onesByPair.set(key, !!(r.config?.fields?.length && r.config?.references?.length));
}
}
}
// ensure each many() has at least one reverse one() with fields
// (illustrative; full inference mirrors normalizeRelation)
} Type guard
import { is } from 'drizzle-orm/entity';
import { One } from 'drizzle-orm/relations';
function isOneWithConfig(v: unknown): boolean {
return is(v, One) && !!(v as any).config?.fields?.length && !!(v as any).config?.references?.length;
} Try / catch
try {
await db.query.users.findMany({ with: { posts: true } });
} catch (e) {
if (e instanceof Error && /not enough information to infer relation/.test(e.message)) {
// add the reverse one() with fields/references on the other table
} else throw e;
} Prevention
- Always pair every many() with a one() that declares fields and references on the other table.
- Add a startup sanity query in dev that exercises each with:{} relation to catch missing reverse definitions.
- For 1:1 or ambiguous relations, set relationName to disambiguate and keep at least one side's config populated.
When it happens
Trigger: Defining only the many() side of a relation without a corresponding one() with fields/references on the other table. Defining two one() relations between the same tables without a relationName to disambiguate (that raises a different error) or with both missing config. A self-referential many() with no reverse one().
Common situations: Setting up relational queries (db.query.users.with.posts) where the posts side was declared as many() but the users side's one() was omitted or declared without fields/references. Incomplete schema during incremental development.
Related errors
- Table "${relation.referencedTable[Table.Symbol.Name]}" not f
- Table "${sourceTable[Table.Symbol.Name]}" not found in schem
- unsupported relation type
- Invalid relation "${relation.fieldName}" for table "${it.sch
- Table "${referencedTableTsName}" not found in schema
AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03).
Data as JSON: /data/errors/a2afcd7c44091699.json.
Report an issue: GitHub.