{"record":{"id":"5abe01a03fb47a4a","repo":"pinpoint-apm/pinpoint","slug":"unknown-scanner-type-classloader-classloader-pr","errorCode":null,"errorMessage":"unknown scanner type classLoader:${classLoader} protectionDomain:${protectionDomain}","messagePattern":"unknown scanner type classLoader:(.+?) protectionDomain:(.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/scanner/ClassScannerFactory.java","lineNumber":59,"sourceCode":"        final URL codeLocation = CodeSourceUtils.getCodeLocation(protectionDomain);\n        if (codeLocation == null) {\n            return new ClassLoaderScanner(classLoader);\n        }\n\n        final Scanner scanner = newURLScanner(codeLocation);\n        if (scanner != null) {\n            return scanner;\n        }\n\n        // workaround for scanning for classes in nested jars - see newURLScanner(URL) below.\n        if (FORCE_CLASS_LOADER_SCANNER || isNestedJar(codeLocation.getPath())) {\n            ClassLoader protectionDomainClassLoader = protectionDomain.getClassLoader();\n            if (protectionDomainClassLoader != null) {\n                return new ClassLoaderScanner(protectionDomainClassLoader);\n            }\n        }\n\n        throw new IllegalArgumentException(\"unknown scanner type classLoader:\" + classLoader + \" protectionDomain:\" + protectionDomain);\n    }\n\n    public static Scanner newScanner(ProtectionDomain protectionDomain) {\n        final URL codeLocation = CodeSourceUtils.getCodeLocation(protectionDomain);\n        if (codeLocation == null) {\n            return null;\n        }\n\n        final Scanner scanner = newURLScanner(codeLocation);\n        if (scanner != null) {\n            return scanner;\n        }\n        return null;\n    }\n\n    private static Scanner newURLScanner(URL codeLocation) {\n        final String protocol = codeLocation.getProtocol();\n        if (isFileProtocol(protocol)) {","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/scanner/ClassScannerFactory.java#L41-L77","documentation":"ClassScannerFactory.newScanner could not determine a scanner strategy for the given class: neither the ClassLoader nor the ProtectionDomain provided a usable class-loading source. It throws IllegalArgumentException describing both inputs.","triggerScenarios":"Calling newScanner with a null classLoader and a ProtectionDomain whose class loader is also null (e.g. bootstrap/primordial classes) so no scanner can be chosen.","commonSituations":"Instrumenting JDK/bootstrap classes loaded by the bootstrap classloader where getClassLoader() returns null and there is no jar fallback; custom classloading setups where classes are defined via reflection/unsafe with a null protection domain classloader.","solutions":["Provide a non-null ClassLoader when requesting the scanner","Ensure the ProtectionDomain has a class loader, or check CodeSource location handling so a JarFileScanner fallback applies","Skip/bootstrap-exclude classes whose loader is null in the transform filter"],"exampleFix":"// before\nScanner s = ClassScannerFactory.newScanner(null, protectionDomain); // both null -> throws\n// after\nClassLoader cl = clazz.getClassLoader() != null ? clazz.getClassLoader() : Thread.currentThread().getContextClassLoader();\nScanner s = cl != null ? ClassScannerFactory.newScanner(cl, protectionDomain) : null;","handlingStrategy":"validation","validationCode":"if (classLoader == null && (protectionDomain == null || protectionDomain.getClassLoader() == null)) { /* skip or use fallback loader */ }","typeGuard":null,"tryCatchPattern":"try { scanner = ClassScannerFactory.newScanner(classLoader, pd); } catch (IllegalArgumentException e) { log.warn(\"no scanner for class, skipping: {}\", e.getMessage()); scanner = null; }","preventionTips":["Exclude bootstrap classes from transform filters","Always pass the class's real ClassLoader","Handle a null scanner return defensively"],"tags":["java","classloader","scanner","instrumentation","bootstrap-classloader"],"backgroundTag":"invalid-argument-value","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}