{"record":{"id":"fc5e885ec662b8cb","repo":"hs-web/hsweb-framework","slug":"join-class-clazz-not-found","errorCode":null,"errorMessage":"join class [\" + clazz + \"] not found!","messagePattern":"join class \\[\" \\+ clazz \\+ \"\\] not found!","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/DefaultQueryHelper.java","lineNumber":535,"sourceCode":"            this.parent = parent;\n            logContext = Context.of(Logger.class, LoggerFactory.getLogger(clazz));\n        }\n\n        private List<JoinConditionalSpecImpl> joins() {\n            return joins == null ? joins = new ArrayList<>(3) : joins;\n        }\n\n        private JoinConditionalSpecImpl getJoinByClass(Class<?> clazz) {\n\n            if (joins != null) {\n                for (JoinConditionalSpecImpl join : joins) {\n                    if (Objects.equals(join.mainClass, clazz)) {\n                        return join;\n                    }\n                }\n            }\n\n            throw new IllegalArgumentException(\"join class [\" + clazz + \"] not found!\");\n        }\n\n        private JoinConditionalSpecImpl getJoinByAlias(String alias) {\n            if (joins != null) {\n                for (JoinConditionalSpecImpl join : joins) {\n                    if (Objects.equals(join.alias, alias)) {\n                        return join;\n                    }\n                }\n            }\n\n            throw new IllegalArgumentException(\"join alias [\" + alias + \"] not found!\");\n        }\n\n        @Override\n        public <From> FromSpec<R> from(Class<From> clazz) {\n            query = parent\n                .database","sourceCodeStart":517,"sourceCodeEnd":553,"githubUrl":"https://github.com/hs-web/hsweb-framework/blob/b2cfc85a57c70bf5b5cf6e7edae2d37102652ec8/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/DefaultQueryHelper.java#L517-L553","documentation":"DefaultQueryHelper's QuerySpec supports join-by-class: when you call join(Class) (or similar), it searches the list of already-registered joins for one whose mainClass equals the requested class. If no registered join matches, it throws this IllegalArgumentException instead of returning null, forcing the caller to fix the class reference.","triggerScenarios":"Calling QuerySpec.join(SomeEntity.class) (or an overload resolving joins by class) where SomeEntity.class was never registered as a join — e.g. the class was never passed to a previous join() call, or a different entity class (a subclass/superclass or a different type) was actually joined.","commonSituations":"Typo or refactor renamed the entity class so the queried class no longer matches the joined one; developer assumes joins are implicit via entity relations but they must be declared explicitly; copy-pasted query code referencing a join from another query builder instance.","solutions":["Call join(TargetEntity.class) to register the join before referencing it by class.","Verify the exact class (FQCN/identity) passed to the join-by-class lookup matches the class used when creating the join, including subclasses vs superclasses.","Inspect the query spec's joins list (debug/toString) to confirm which classes were actually joined.","If resolving dynamically, wrap the lookup and register the join lazily when the lookup fails."],"exampleFix":"// before\nQueryHelper wherever = helper.createQuery(UserEntity.class)\n    .join(RoleEntity.class);\n// RoleEntity was never joined -> IllegalArgumentException\n\n// after\nQuerySpec<UserEntity> spec = helper.createQuery(UserEntity.class)\n    .leftJoin(RoleEntity.class, on -> on.eq(\"userId\", \"id\"));\nspec.join(RoleEntity.class); // now found among registered joins","handlingStrategy":"try-catch","validationCode":"// Java\nboolean joined = spec.getJoins().stream()\n    .anyMatch(j -> Objects.equals(j.getMainClass(), TargetEntity.class));\nif (!joined) { spec.leftJoin(TargetEntity.class, on -> on.eq(\"id\", \"targetId\")); }","typeGuard":null,"tryCatchPattern":"// Java\ntry {\n    spec.join(TargetEntity.class);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"join class\")) {\n        spec.leftJoin(TargetEntity.class, on -> on.eq(\"id\", \"targetId\"));\n    } else { throw e; }\n}","preventionTips":["Always declare joins explicitly before referencing them by class.","Centralize join definitions in builder constants so class references stay in sync.","After refactors, grep for join-by-class usages and verify against declared joins."],"tags":["java","query","join","illegal-argument"],"backgroundTag":"resource-not-found","analyzedSha":"b2cfc85a57c70bf5b5cf6e7edae2d37102652ec8","analyzedAt":"2026-09-13T09:05:02.172Z","contentChangedAt":"2026-09-13T09:05:02.172Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}