{"id":"c3e472cfb2616c7b","repo":"drizzle-team/drizzle-orm","slug":"table-referencedtabletsname-not-found-in-sche","errorCode":null,"errorMessage":"Table \"${referencedTableTsName}\" not found in schema","messagePattern":"Table \"(.+?)\" not found in schema","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/relations.ts","lineNumber":580,"sourceCode":"\trelation: Relation,\n): NormalizedRelation {\n\tif (is(relation, One) && relation.config) {\n\t\treturn {\n\t\t\tfields: relation.config.fields,\n\t\t\treferences: relation.config.references,\n\t\t};\n\t}\n\n\tconst referencedTableTsName = tableNamesMap[getTableUniqueName(relation.referencedTable)];\n\tif (!referencedTableTsName) {\n\t\tthrow new Error(\n\t\t\t`Table \"${relation.referencedTable[Table.Symbol.Name]}\" not found in schema`,\n\t\t);\n\t}\n\n\tconst referencedTableConfig = schema[referencedTableTsName];\n\tif (!referencedTableConfig) {\n\t\tthrow new Error(`Table \"${referencedTableTsName}\" not found in schema`);\n\t}\n\n\tconst sourceTable = relation.sourceTable;\n\tconst sourceTableTsName = tableNamesMap[getTableUniqueName(sourceTable)];\n\tif (!sourceTableTsName) {\n\t\tthrow new Error(\n\t\t\t`Table \"${sourceTable[Table.Symbol.Name]}\" not found in schema`,\n\t\t);\n\t}\n\n\tconst reverseRelations: Relation[] = [];\n\tfor (\n\t\tconst referencedTableRelation of Object.values(\n\t\t\treferencedTableConfig.relations,\n\t\t)\n\t) {\n\t\tif (\n\t\t\t(relation.relationName","sourceCodeStart":562,"sourceCodeEnd":598,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/relations.ts#L562-L598","documentation":"normalizeRelation() throws when the referenced table's TypeScript name was found in tableNamesMap but is absent from the actual schema config object. This indicates an inconsistency between the table-name map and the relational schema built by extractTablesRelationalConfig - typically a partial or mismatched schema where a relation target exists by name but its config was not registered.","triggerScenarios":"Passing two different schema objects to tableNamesMap and the relational schema, or a relations definition whose target table key differs from what extractTablesRelationalConfig produced. Mixed imports where the same logical table is represented by two different objects.","commonSituations":"Build/bundler tree-shaking dropping a table from the schema map but keeping it in relations. Manual construction of relational config instead of using drizzle({schema}). Duplicated table definitions across files.","solutions":["Always build the relational schema via drizzle({ schema }) with a single complete schema object exported from one module.","Audit for duplicate table definitions (same table name defined in two files) and consolidate to a single source.","Disable aggressive tree-shaking for the schema module or mark schema exports as side-effectful if the bundler drops them."],"exampleFix":"// before: schema map and relations out of sync\nconst db = drizzle(client, { schema: { users, posts } }); // but relations reference a 'comments' table not in schema\n\n// after: single complete schema\nimport * as schema from './schema';\nconst db = drizzle(client, { schema });","handlingStrategy":"validation","validationCode":"// Ensure the relational schema is built from a single complete schema object\n// so tableNamesMap and the schema config stay consistent.\nimport * as schema from './schema';\n\nfunction assertNoTableDuplicates(schema: Record<string, any>) {\n  const seen = new Map<string, string>();\n  for (const [key, v] of Object.entries(schema)) {\n    if (v?.[Symbol.for('drizzle:entityKind')] === 'Table') {\n      const unique = v[Symbol.for('drizzle:Name')];\n      if (seen.has(unique)) {\n        throw new Error(`Duplicate table \"${unique}\" (keys: ${seen.get(unique)}, ${key})`);\n      }\n      seen.set(unique, key);\n    }\n  }\n}\nassertNoTableDuplicates(schema);\nconst db = drizzle(client, { schema });","typeGuard":"// Detect that tableNamesMap and schema disagree by checking every\n// relation target key resolves to a config entry.\nfunction schemaIsComplete(schema: Record<string, any>): boolean {\n  return Object.values(schema).every((v) => v && typeof v === 'object');\n}","tryCatchPattern":"try {\n  await db.query.users.findFirst();\n} catch (e) {\n  if (e instanceof Error && /not found in schema/.test(e.message)) {\n    // rebuild schema as a single barrel export and re-pass\n  } else throw e;\n}","preventionTips":["Build relational config only via drizzle({ schema }) with one consolidated schema module.","Eliminate duplicate table definitions across files.","Mark schema modules as side-effectful in bundler config to prevent tree-shaking dropping tables."],"tags":["relations","schema","configuration","inconsistency"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}