{"record":{"id":"23cbf181a6900a5b","repo":"apache/beam","slug":"queryplanner-class-s-does-not-have-an-accessible-static","errorCode":null,"errorMessage":"QueryPlanner class %s does not have an accessible static field 'FACTORY' of type QueryPlanner.Factory","messagePattern":"QueryPlanner class (.+?) does not have an accessible static field 'FACTORY' of type QueryPlanner\\.Factory","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/BeamSqlEnv.java","lineNumber":351,"sourceCode":"      } catch (ClassNotFoundException exc) {\n        throw new RuntimeException(\n            \"Cannot find requested QueryPlanner class: \" + queryPlannerClassName, exc);\n      }\n\n      // This try/catch kept deliberately tight to ensure that we _only_ catch exceptions due to\n      // this reflective access.\n      QueryPlanner.Factory factory;\n      try {\n        // See https://github.com/typetools/jdk/pull/235#pullrequestreview-3400922783\n        @SuppressWarnings(\"nullness\")\n        Object queryPlannerFactoryObj =\n            checkStateNotNull(\n                queryPlannerClass.getField(\"FACTORY\").get(null),\n                \"Static field %s.FACTORY is null. It must be a QueryPlanner.Factory instance.\",\n                queryPlannerClass);\n        factory = (QueryPlanner.Factory) queryPlannerFactoryObj;\n      } catch (NoSuchFieldException | IllegalAccessException exc) {\n        throw new RuntimeException(\n            String.format(\n                \"QueryPlanner class %s does not have an accessible static field 'FACTORY' of type QueryPlanner.Factory\",\n                queryPlannerClassName),\n            exc);\n      }\n\n      return factory.createPlanner(jdbcConnection, ruleSets);\n    }\n  }\n}\n","sourceCodeStart":333,"sourceCodeEnd":362,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/BeamSqlEnv.java#L333-L362","documentation":"After loading the planner class reflectively, instantiatePlanner reads its public static FACTORY field of type QueryPlanner.Factory. If the field is missing, inaccessible, or of the wrong shape (NoSuchFieldException/IllegalAccessException/failed checkStateNotNull cast context), it throws a RuntimeException stating the class must expose an accessible static FACTORY.","triggerScenarios":"Providing a custom QueryPlanner class that lacks 'public static final QueryPlanner.Factory FACTORY', has it private/package-private, or names a non-planner class entirely.","commonSituations":"Implementing a custom planner against an older Beam API where FACTORY naming changed, pointing the planner config at a helper or wrapper class, refactors dropping the field.","solutions":["Add a public static field named FACTORY of type QueryPlanner.Factory to the planner class","Ensure the field is accessible (public, non-null, initialized)","If the class can't provide a FACTORY, wrap it or use the default BeamQueryPlanner","Check the beam-sdks-java-extensions-sql version for the expected planner contract"],"exampleFix":"// before\npublic class MyPlanner implements QueryPlanner { ... } // no FACTORY\n// after\npublic class MyPlanner implements QueryPlanner {\n  public static final QueryPlanner.Factory FACTORY = ...;\n  ...\n}","handlingStrategy":"validation","validationCode":"Class<?> c = Class.forName(plannerClassName);\nc.getField(\"FACTORY\"); // throws NoSuchFieldException early\nassert QueryPlanner.Factory.class.isAssignableFrom(c.getField(\"FACTORY\").getType());","typeGuard":"boolean hasFactoryField(Class<?> c) {\n  try { return QueryPlanner.Factory.class.isAssignableFrom(c.getField(\"FACTORY\").getType()); }\n  catch (NoSuchFieldException e) { return false; }\n}","tryCatchPattern":"try { env = builder.build(); } catch (RuntimeException e) { if (e.getMessage().contains(\"FACTORY\")) { /* planner class is not a valid planner */ } throw e; }","preventionTips":["Implement custom planners against the current QueryPlanner contract","Always declare public static QueryPlanner.Factory FACTORY","Unit-test planner instantiation before deployment"],"tags":["sql","reflection","planner"],"backgroundTag":"missing-required-config-field","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}