{"record":{"id":"65b67e377487bb26","repo":"typeorm/typeorm","slug":"entity-to-work-with-is-not-specified","errorCode":null,"errorMessage":"Entity to work with is not specified!","messagePattern":"Entity to work with is not specified!","errorType":"exception","errorClass":"TypeORMError","httpStatus":null,"severity":"error","filePath":"src/query-builder/QueryExpressionMap.ts","lineNumber":465,"sourceCode":"        return alias\n    }\n\n    findColumnByAliasExpression(\n        aliasExpression: string,\n    ): ColumnMetadata | undefined {\n        const [aliasName, propertyPath] = aliasExpression.split(\".\")\n        const alias = this.findAliasByName(aliasName)\n        return alias.metadata.findColumnWithPropertyName(propertyPath)\n    }\n\n    /**\n     * Gets relation metadata of the relation this query builder works with.\n     *\n     * todo: add proper exceptions\n     */\n    get relationMetadata(): RelationMetadata {\n        if (!this.mainAlias)\n            throw new TypeORMError(`Entity to work with is not specified!`) // todo: better message\n\n        const relationMetadata =\n            this.mainAlias.metadata.findRelationWithPropertyPath(\n                this.relationPropertyPath,\n            )\n        if (!relationMetadata)\n            throw new TypeORMError(\n                `Relation ${this.relationPropertyPath} was not found in entity ${this.mainAlias.name}`,\n            ) // todo: better message\n\n        return relationMetadata\n    }\n\n    /**\n     * Copies all properties of the current QueryExpressionMap into a new one.\n     * Useful when QueryBuilder needs to create a copy of itself.\n     */\n    clone(): QueryExpressionMap {","sourceCodeStart":447,"sourceCodeEnd":483,"githubUrl":"https://github.com/typeorm/typeorm/blob/df07bf1ef46f62f72077699fe4cd2c03b2f666e4/src/query-builder/QueryExpressionMap.ts#L447-L483","documentation":"Thrown by the `relationMetadata` getter in QueryExpressionMap when no main alias has been set on the query builder. The getter is invoked every time a RelationQueryBuilder operation (set/add/remove/loadMany/loadOne) needs to resolve which entity class the relation lives on. Without a main alias the builder cannot look up relation metadata, so it aborts before issuing any SQL. This is a programming/usage error, not a data or database problem.","triggerScenarios":"Calling `.relation(\"someProp\")` (single-argument form) on a raw DataSource/EntityManager QueryBuilder that has no main alias, then invoking `.of(x).set(y)` / `.add(y)` / `.loadMany()`. The single-argument `relation(propertyPath)` overload deliberately does NOT set a main alias; only the two-argument `relation(EntityTarget, propertyPath)` does. Any subsequent access to `expressionMap.relationMetadata` triggers the throw.","commonSituations":"Using `dataSource.createQueryBuilder().relation(\"photos\").of(user).set(photo)` instead of going through a typed repository; refactoring code that previously called `.relation()` on a `Repository<T>` (which injects the entity target) to call it on a bare EntityManager; copying a snippet from a tutorial that assumed a repository context into a DataSource-based context.","solutions":["Use the two-argument form so the builder knows the entity: `dataSource.createQueryBuilder().relation(User, \"photos\").of(user).set(photo)`.","Prefer going through the repository, which supplies the entity target automatically: `userRepository.relation(\"photos\").of(user).set(photo)`.","If you already have a SelectQueryBuilder with a main alias, chain `.relation()` off that builder instead of creating a fresh one from the DataSource."],"exampleFix":"// before\nawait dataSource\n  .createQueryBuilder()\n  .relation(\"photos\")          // no entity target -> main alias unset\n  .of(user)\n  .set(photo);\n\n// after (two-argument form)\nawait dataSource\n  .createQueryBuilder()\n  .relation(User, \"photos\")    // entity target -> main alias set\n  .of(user)\n  .set(photo);\n\n// after (via repository)\nawait userRepository\n  .relation(\"photos\")\n  .of(user)\n  .set(photo);","handlingStrategy":"validation","validationCode":"// Before calling relation ops, ensure a main alias exists.\nfunction assertRelationTarget(qb: SelectQueryBuilder<any>) {\n  if (!qb.expressionMap.mainAlias) {\n    throw new Error(\"Call .relation(Entity, 'prop') with an entity target, or use a Repository.\");\n  }\n}","typeGuard":"function hasMainAlias(qb: QueryBuilder<any>): boolean {\n  return !!qb.expressionMap.mainAlias;\n}","tryCatchPattern":null,"preventionTips":["Prefer Repository.relation(prop) — it injects the entity target automatically.","When using DataSource.createQueryBuilder(), always pass two arguments to .relation().","Wrap relation-API usage in a typed helper that asserts the main alias is set."],"tags":["query-builder","relation","usage-error","metadata"],"backgroundTag":null,"analyzedSha":"df07bf1ef46f62f72077699fe4cd2c03b2f666e4","analyzedAt":"2026-08-07T05:58:41.164Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}