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

  1. 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] }) })).
  2. If both sides are one() (e.g., 1:1), add a relationName to disambiguate and ensure at least one side declares fields/references.
  3. 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

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


AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03). Data as JSON: /data/errors/a2afcd7c44091699.json. Report an issue: GitHub.