apache/dubbo · error · IllegalArgumentException
non-public interfaces from different packages
Error message
non-public interfaces from different packages
What it means
Thrown by Proxy.buildProxyClass when one or more interfaces are non-public and their package differs from that of ics[0]. The generated proxy class is placed in the package of the first interface so it can access package-private interfaces; a non-public interface from a different package cannot be implemented from there, so Dubbo aborts with IllegalArgumentException.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java:133
return sb.toString();
}
private static Class<?> buildProxyClass(ClassLoader cl, Class<?>[] ics, ProtectionDomain domain) {
ClassGenerator ccp = null;
try {
ccp = ClassGenerator.newInstance(cl);
Set<String> worked = new HashSet<>();
List<Method> methods = new ArrayList<>();
String pkg = ics[0].getPackage().getName();
Class<?> neighbor = ics[0];
for (Class<?> ic : ics) {
String npkg = ic.getPackage().getName();
if (!Modifier.isPublic(ic.getModifiers())) {
if (!pkg.equals(npkg)) {
throw new IllegalArgumentException("non-public interfaces from different packages");
}
}
ccp.addInterface(ic);
for (Method method : ic.getMethods()) {
String desc = ReflectUtils.getDesc(method);
if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) {
continue;
}
worked.add(desc);
int ix = methods.size();
Class<?> rt = method.getReturnType();
Class<?>[] pts = method.getParameterTypes();
StringBuilder code = new StringBuilder("Object[] args = new Object[")
.append(pts.length)View on GitHub (pinned to 3a3043227f)
Solutions
- Make all interfaces passed to getProxy public.
- If some must stay package-private, keep them all in the same package as ics[0].
- Order the array so ics[0] is in the same package as every other non-public interface (only helps if all non-public share one package).
Example fix
// before
package a.b; interface InternalA {} // package-private
package c.d; public interface PublicB {}
Proxy.getProxy(InternalA.class, PublicB.class);
// after
package a.b; public interface InternalA {} // promote to public Defensive patterns
Strategy: validation
Validate before calling
String pkg0 = ics[0].getPackageName();
for (Class<?> ic : ics) {
if (!Modifier.isPublic(ic.getModifiers()) && !ic.getPackageName().equals(pkg0)) {
throw new IllegalArgumentException("non-public interface " + ic + " from a different package");
}
} Prevention
- Make all proxied interfaces public.
- Keep any package-private interfaces in the same package as ics[0].
- Validate interface visibility and packages before calling getProxy.
When it happens
Trigger: Proxy.getProxy(ics) where ics mixes package-private interfaces from package X with a first interface (or other non-public interface) from package Y.
Common situations: Internal SPI interfaces that are not public and originate from different modules/packages; combining a public API interface with a package-private extension interface from another package.
Related errors
- non-public interfaces class from different packages
- non-public delegate class from different packages
- interface limit exceeded
- {} is not a interface.
- ${cause.message}
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/077bb3620939528d.
Report an issue: GitHub.