{"record":{"id":"2db3e2bb6b0e0ff6","repo":"apache/dubbo","slug":"interface-limit-exceeded","errorCode":null,"errorMessage":"interface limit exceeded","messagePattern":"interface limit exceeded","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java","lineNumber":65,"sourceCode":"\n    private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0);\n    private static final Map<ClassLoader, Map<String, Proxy>> PROXY_CACHE_MAP = new WeakHashMap<>();\n\n    private final Class<?> classToCreate;\n\n    protected Proxy(Class<?> classToCreate) {\n        this.classToCreate = classToCreate;\n    }\n\n    /**\n     * Get proxy.\n     *\n     * @param ics interface class array.\n     * @return Proxy instance.\n     */\n    public static Proxy getProxy(Class<?>... ics) {\n        if (ics.length > MAX_PROXY_COUNT) {\n            throw new IllegalArgumentException(\"interface limit exceeded\");\n        }\n\n        // ClassLoader from App Interface should support load some class from Dubbo\n        ClassLoader cl = ics[0].getClassLoader();\n        ProtectionDomain domain = ics[0].getProtectionDomain();\n\n        // use interface class name list as key.\n        String key = buildInterfacesKey(cl, ics);\n\n        // get cache by class loader.\n        final Map<String, Proxy> cache;\n        synchronized (PROXY_CACHE_MAP) {\n            cache = PROXY_CACHE_MAP.computeIfAbsent(cl, k -> new ConcurrentHashMap<>());\n        }\n\n        Proxy proxy = cache.get(key);\n        if (proxy == null) {\n            synchronized (ics[0]) {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java#L47-L83","documentation":"Thrown by Proxy.getProxy when the number of interfaces passed exceeds MAX_PROXY_COUNT (65535). It is a sanity cap: a generated proxy with that many interfaces would be pathological and almost always indicates a caller bug that built a huge array.","triggerScenarios":"Proxy.getProxy(ics) with ics.length > 65535, e.g. accidentally passing every loaded interface or a collection flattened into a Class<?> array.","commonSituations":"A loop that accumulates interfaces without dedup; passing Class.getInterfaces() of many classes merged together; a reflective scan that gathered transitive interfaces; essentially always a programming bug, never a realistic workload.","solutions":["Check how the ics array is built; deduplicate and keep only the interfaces you actually need to proxy.","If you genuinely need many interfaces, split into several proxies.","Add an assertion logging ics.length before calling getProxy to catch runaway arrays."],"exampleFix":"// before\nClass<?>[] all = collectEveryInterface(classpath); // thousands\nProxy.getProxy(all);\n\n// after\nSet<Class<?>> needed = new HashSet<>(Arrays.asList(ServiceA.class, ServiceB.class));\nProxy.getProxy(needed.toArray(new Class<?>[0]));","handlingStrategy":"validation","validationCode":"if (ics.length > 65535) {\n    throw new IllegalArgumentException(\"too many interfaces: \" + ics.length);\n}\nProxy.getProxy(ics);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Deduplicate the interface array before calling getProxy.","Log ics.length during development to catch runaway arrays early.","Only include interfaces you actually need to proxy."],"tags":["bytecode","proxy","validation"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}