apache/beam · error · LinkageError
${e.getMessage()}
Error message
${e.getMessage()} What it means
While selecting a class-loading strategy for the generated invoker, any ReflectiveOperationException (e.g. from Lookup.privateLookupIn) is wrapped in a LinkageError whose message is just the original exception's message. It signals the JVM could not perform the reflective lookup needed to enable code generation.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/ByteBuddyDoFnInvokerFactory.java:718
Method privateLookupIn =
methodHandles.getMethod(
"privateLookupIn",
Class.class,
Class.forName("java.lang.invoke.MethodHandles$Lookup"));
Object privateLookup =
checkStateNotNull(
privateLookupIn.invoke(nullObjectForStaticMethodInvocation, targetClass, lookup),
"MethodHandles.Lookup.privateLookupIn not available");
strategy = ClassLoadingStrategy.UsingLookup.of(privateLookup);
} else if (ClassInjector.UsingReflection.isAvailable()) {
strategy = ClassLoadingStrategy.Default.INJECTION;
} else {
throw new IllegalStateException("No code generation strategy available");
}
return strategy;
} catch (ReflectiveOperationException e) {
throw new LinkageError(e.getMessage(), e);
}
}
private static Implementation getRestrictionCoderDelegation(
TypeDescription doFnType, DoFnSignature signature) {
if (signature.processElement().isSplittable()) {
if (signature.getRestrictionCoder() == null) {
checkStateNotNull(
signature.getInitialRestriction(),
"@GetRestrictionCoder provided but @GetInitialRestriction not provided:"
+ " please add @GetInitialRestriction");
return MethodDelegation.to(
new DefaultRestrictionCoder(signature.getInitialRestriction().restrictionT()));
} else {
return new DowncastingParametersMethodDelegation(
doFnType, signature.getRestrictionCoder().targetMethod());
}
} else {View on GitHub (pinned to 12126d8942)
Solutions
- Add --add-opens / --add-reads JVM flags granting access to the relevant module/package (e.g. --add-opens java.base/java.lang=ALL-UNNAMED).
- Move the DoFn classes to the classpath (unnamed module) instead of a named module.
- Read e.getMessage() in the LinkageError to identify which reflective call failed and fix access for it.
Example fix
// before java --module-path mods -m app/Main // LinkageError: access denied // after java --module-path mods --add-reads app=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED -m app/Main
Defensive patterns
Strategy: try-catch
Try / catch
try {
invoker = ByteBuddyDoFnInvokerFactory.newByteBuddyInvoker(fn);
} catch (LinkageError e) {
LOG.error("Reflective lookup failed: " + e.getMessage(), e);
throw e;
} Prevention
- Add --add-opens/--add-reads flags when DoFns live in named modules on Java 9+.
- Keep Beam classes on the classpath (unnamed module) rather than in named modules.
- Read the LinkageError's message — it names the failing reflective operation.
When it happens
Trigger: Lookup.privateLookupIn(targetClass, lookup) throws due to module access denial, or another reflective step in strategy selection fails on the current JVM.
Common situations: Java 9+ strong encapsulation without --add-opens; DoFn classes in a named module without the required --add-reads; container security managers.
Related errors
- Unable to bind invoker for ${fnClass}
- Failed to locate required method ${className}.${methodName}
- Failed to locate ProcessContinuation.stop()
- No code generation strategy available
- No code generation strategy available
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/a37cf5f21a31790c.
Report an issue: GitHub.