{"record":{"id":"f63a70f3a4c5651c","repo":"apache/cassandra","slug":"java-udf-validation-failed","errorCode":null,"errorMessage":"Java UDF validation failed: ","messagePattern":"Java UDF validation failed: ","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/functions/JavaBasedUDFunction.java","lineNumber":330,"sourceCode":"\n                if (fullSource)\n                    throw new InvalidRequestException(\"Java source compilation failed:\\n\" + problems + \"\\n generated source:\\n\" + javaSource);\n                else\n                    throw new InvalidRequestException(\"Java source compilation failed:\\n\" + problems);\n            }\n\n            // Verify the UDF bytecode against use of probably dangerous code\n            Set<String> errors = udfByteCodeVerifier.verify(targetClassName, targetClassLoader.classData(targetClassName));\n            String validDeclare = \"not allowed method declared: \" + executeInternalName + '(';\n            for (Iterator<String> i = errors.iterator(); i.hasNext();)\n            {\n                String error = i.next();\n                // we generate a random name of the private, internal execute method, which is detected by the byte-code verifier\n                if (error.startsWith(validDeclare))\n                    i.remove();\n            }\n            if (!errors.isEmpty())\n                throw new InvalidRequestException(\"Java UDF validation failed: \" + errors);\n\n            // Load the class and create a new instance of it\n            Thread thread = Thread.currentThread();\n            ClassLoader orig = thread.getContextClassLoader();\n            try\n            {\n                thread.setContextClassLoader(UDFunction.udfClassLoader);\n                // Execute UDF intiialization from UDF class loader\n\n                Class cls = Class.forName(targetClassName, false, targetClassLoader);\n\n                // Count only non-synthetic methods, so code coverage instrumentation doesn't cause a miscount\n                int nonSyntheticMethodCount = 0;\n                for (Method m : cls.getDeclaredMethods())\n                {\n                    if (!m.isSynthetic())\n                    {\n                        nonSyntheticMethodCount += 1;","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/functions/JavaBasedUDFunction.java#L312-L348","documentation":"After compiling a Java UDF, the bytecode verifier scans the class for dangerous constructs (reflection, thread ops, I/O, static fields, etc.). If disallowed constructs are found, JavaBasedUDFunction throws this InvalidRequestException listing the violations. It means the UDF body compiled but uses operations the UDF sandbox forbids.","triggerScenarios":"CREATE FUNCTION whose Java body references Thread.currentThread(), classloading, reflection, static mutable state, I/O, or other constructs flagged by UDFByteCodeVerifier; the generated execute method has an unexpected signature (though the internal-name mismatch is filtered out).","commonSituations":"Porting normal Java code (logging, I/O, caching in statics) into UDFs; calling Cassandra/driver APIs from a UDF; trying multithreading or System calls inside UDFs.","solutions":["Remove the forbidden constructs listed after 'Java UDF validation failed:' (e.g. Thread, reflection, static fields, I/O).","Keep the UDF body pure computation over its arguments and return value only.","Compute side effects in the application layer, not the UDF.","Drop and recreate the function after cleaning the body; consult UDFByteCodeVerifier for the disallowed list."],"exampleFix":"// before\n' Thread t = Thread.currentThread(); return x + 1; '\n// after\n' return x + 1; '","handlingStrategy":"validation","validationCode":"// pre-scan body for sandbox-forbidden tokens before DDL:\nSet<String> forbidden = Set.of(\"Thread\",\"Class\",\"forName\",\"System.\",\"File\",\"Runtime\",\"reflect\",\"static\");\nfor (String tok : forbidden) if (body.contains(tok)) throw new IllegalArgumentException(\"UDF body uses forbidden construct: \" + tok);","typeGuard":null,"tryCatchPattern":"try { session.execute(createFunctionDdl); } catch (InvalidRequestException e) { if (e.getMessage().contains(\"Java UDF validation failed\")) { /* remove listed forbidden constructs and re-CREATE */ } else throw e; }","preventionTips":["Keep UDF bodies pure: arguments in, value out","Never use threads, reflection, I/O, or static state in UDFs","Review UDFByteCodeVerifier's disallowed list before writing UDFs","Move side effects to the application layer"],"tags":["udf","sandbox","bytecode"],"backgroundTag":"schema-validation-failed","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}