{"record":{"id":"96bb613b9325d596","repo":"apache/beam","slug":"cannot-detect-classpath-classload-is-null-is-it-the","errorCode":null,"errorMessage":"Cannot detect classpath: classload is null (is it the bootstrap classloader?)","messagePattern":"Cannot detect classpath: classload is null \\(is it the bootstrap classloader\\?\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/kryo/src/main/java/org/apache/beam/sdk/extensions/kryo/KryoState.java","lineNumber":66,"sourceCode":"    private final ThreadLocal<Map<String, KryoState>> kryoStateMap =\n        ThreadLocal.withInitial(HashMap::new);\n\n    KryoState getOrCreate(KryoCoder<?> coder) {\n      return kryoStateMap\n          .get()\n          .computeIfAbsent(\n              coder.getInstanceId(),\n              k -> {\n                final Kryo kryo = new Kryo();\n                // fallback in case serialized class does not have default constructor\n                kryo.setInstantiatorStrategy(\n                    new DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));\n                kryo.setReferences(coder.getOptions().getReferences());\n                kryo.setRegistrationRequired(coder.getOptions().getRegistrationRequired());\n\n                ClassLoader classLoader = Thread.currentThread().getContextClassLoader();\n                if (classLoader == null) {\n                  throw new RuntimeException(\n                      \"Cannot detect classpath: classload is null (is it the bootstrap classloader?)\");\n                }\n\n                kryo.setClassLoader(classLoader);\n                // first id of user provided class registration\n                final int firstRegistrationId = kryo.getNextRegistrationId();\n                // register user provided classes\n                for (KryoRegistrar registrar : coder.getRegistrars()) {\n                  registrar.registerClasses(kryo);\n                }\n                return new KryoState(\n                    kryo,\n                    firstRegistrationId,\n                    new InputChunked(coder.getOptions().getBufferSize()),\n                    new OutputChunked(coder.getOptions().getBufferSize()));\n              });\n    }\n  }","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/kryo/src/main/java/org/apache/beam/sdk/extensions/kryo/KryoState.java#L48-L84","documentation":"When lazily creating the shared Kryo instance, KryoState reads the current thread's context ClassLoader to scope Kryo's classpath/class resolution. If the context ClassLoader is null (typically only the bootstrap ClassLoader situation), it throws a RuntimeException because Kryo could not resolve application classes. This is an environment/threading problem, not a data problem.","triggerScenarios":"KryoState.getOrCreate executing on a thread whose context ClassLoader was never set or was explicitly cleared (null), e.g. certain runner/system threads or threads created before classloader configuration.","commonSituations":"Running on a runner or container whose worker threads lack a context classloader; using Kryo coder inside custom thread pools where Thread.currentThread().setContextClassLoader was never called; bootstrap-classloader-only environments.","solutions":["Set the context ClassLoader on the thread before decoding: Thread.currentThread().setContextClassLoader(AppClass.class.getClassLoader()).","Configure the runner/worker environment so application threads have a proper context classloader.","If spawning your own threads, pass and set the classloader from the creating thread.","Avoid relying on the bootstrap classloader; ensure code runs on a worker classloader containing user code."],"exampleFix":"// before: custom thread without classloader\nnew Thread(() -> pipeline.run()).start();\n// after\nThread t = new Thread(() -> pipeline.run());\nt.setContextClassLoader(MyPipeline.class.getClassLoader());\nt.start();","handlingStrategy":"validation","validationCode":"if (Thread.currentThread().getContextClassLoader() == null) { Thread.currentThread().setContextClassLoader(MyClass.class.getClassLoader()); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never leave worker threads without a context ClassLoader","Set the classloader explicitly in custom thread pools and runners","Ensure user code runs on a worker classloader, not the bootstrap one"],"tags":["java","classloader","kryo","runtime"],"backgroundTag":"missing-env-var","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}