apache/beam · error · RuntimeException
QueryPlanner class %s does not have an accessible static fie
Error message
QueryPlanner class %s does not have an accessible static field 'FACTORY' of type QueryPlanner.Factory
What it means
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.
Source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/BeamSqlEnv.java:351
} catch (ClassNotFoundException exc) {
throw new RuntimeException(
"Cannot find requested QueryPlanner class: " + queryPlannerClassName, exc);
}
// This try/catch kept deliberately tight to ensure that we _only_ catch exceptions due to
// this reflective access.
QueryPlanner.Factory factory;
try {
// See https://github.com/typetools/jdk/pull/235#pullrequestreview-3400922783
@SuppressWarnings("nullness")
Object queryPlannerFactoryObj =
checkStateNotNull(
queryPlannerClass.getField("FACTORY").get(null),
"Static field %s.FACTORY is null. It must be a QueryPlanner.Factory instance.",
queryPlannerClass);
factory = (QueryPlanner.Factory) queryPlannerFactoryObj;
} catch (NoSuchFieldException | IllegalAccessException exc) {
throw new RuntimeException(
String.format(
"QueryPlanner class %s does not have an accessible static field 'FACTORY' of type QueryPlanner.Factory",
queryPlannerClassName),
exc);
}
return factory.createPlanner(jdbcConnection, ruleSets);
}
}
}
View on GitHub (pinned to 12126d8942)
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
Example fix
// before
public class MyPlanner implements QueryPlanner { ... } // no FACTORY
// after
public class MyPlanner implements QueryPlanner {
public static final QueryPlanner.Factory FACTORY = ...;
...
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = Class.forName(plannerClassName);
c.getField("FACTORY"); // throws NoSuchFieldException early
assert QueryPlanner.Factory.class.isAssignableFrom(c.getField("FACTORY").getType()); Type guard
boolean hasFactoryField(Class<?> c) {
try { return QueryPlanner.Factory.class.isAssignableFrom(c.getField("FACTORY").getType()); }
catch (NoSuchFieldException e) { return false; }
} Try / catch
try { env = builder.build(); } catch (RuntimeException e) { if (e.getMessage().contains("FACTORY")) { /* planner class is not a valid planner */ } throw e; } Prevention
- Implement custom planners against the current QueryPlanner contract
- Always declare public static QueryPlanner.Factory FACTORY
- Unit-test planner instantiation before deployment
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Cannot find requested QueryPlanner class: ${queryPlannerClas
- failed to matched a %v field for SQL column: %v
- SqlTransform can only be applied to schema'd transforms. Ple
- error when invoking Coder factory method
- cannot register Coder : does not have an accessible method n
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/23cbf181a6900a5b.
Report an issue: GitHub.