{"record":{"id":"413608f1d4b2f244","repo":"pentaho/pentaho-kettle","slug":"unable-to-obtain-checksum-of-udjc","errorCode":null,"errorMessage":"Unable to obtain checksum of UDJC - ","messagePattern":"Unable to obtain checksum of UDJC - ","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/userdefinedjavaclass/UserDefinedJavaClassDef.java","lineNumber":57,"sourceCode":"    super();\n    this.classType = classType;\n    this.className = className;\n    this.source = source;\n    classActive = true;\n  }\n\n  public int hashCode() {\n    return Objects.hash( className, source );\n  }\n\n  public String getChecksum() throws KettleStepException {\n    String ck = this.className + this.source;\n    try {\n      byte[] b = MessageDigest.getInstance( \"MD5\" ).digest( ck.getBytes() );\n      return Hex.encodeHexString( b );\n    } catch ( Exception ex ) {\n      // Can't get MD5 hashcode ?\n      throw new KettleStepException( \"Unable to obtain checksum of UDJC - \" + this.className );\n    }\n  }\n\n  public ClassType getClassType() {\n    return classType;\n  }\n\n  public void setClassType( ClassType classType ) {\n    this.classType = classType;\n  }\n\n  public String getSource() {\n    return this.source;\n  }\n\n  public Object clone() throws CloneNotSupportedException {\n    return super.clone();\n  }","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/userdefinedjavaclass/UserDefinedJavaClassDef.java#L39-L75","documentation":"UserDefinedJavaClassDef.getChecksum computes an MD5 over className+source; if MessageDigest.getInstance(\"MD5\") or digest/encoding fails (essentially only when the JRE lacks the MD5 provider), it throws KettleStepException \"Unable to obtain checksum of UDJC - <className>\". Called by checksum(), used to detect source changes for class recompilation.","triggerScenarios":"MessageDigest.getInstance(\"MD5\") throwing NoSuchAlgorithmException — a non-standard or stripped JCE provider set — or unexpected exceptions during digest computation.","commonSituations":"Running on a hardened/custom JVM (e.g. FIPS-configured) where MD5 is disabled; extremely minimal JRE distributions without the standard SunJCE provider.","solutions":["Run on a standard Oracle/OpenJDK JVM where the MD5 MessageDigest is available.","Remove JVM security restrictions disabling MD5 (java.security configuration / FIPS policy).","If the JVM policy cannot change, patch getChecksum to use an allowed algorithm (e.g. SHA-256)."],"exampleFix":"// before\nbyte[] b = MessageDigest.getInstance( \"MD5\" ).digest( ck.getBytes() );\n// after (when MD5 is unavailable)\nbyte[] b = MessageDigest.getInstance( \"SHA-256\" ).digest( ck.getBytes() );","handlingStrategy":"try-catch","validationCode":"// verify MD5 availability before running UDJC transformations\ntry { MessageDigest.getInstance(\"MD5\"); } catch (NoSuchAlgorithmException e) { /* JVM lacks MD5: fix provider or use SHA-256 */ }","typeGuard":"boolean md5Available() { try { MessageDigest.getInstance(\"MD5\"); return true; } catch (NoSuchAlgorithmException e) { return false; } }","tryCatchPattern":"try { String ck = def.checksum(); ... } catch (KettleStepException e) { logError(\"Cannot checksum UDJC class (JCE policy?): \" + e.getMessage()); }","preventionTips":["Run Kettle on a standard OpenJDK/Oracle JVM","Avoid FIPS policies that disable MD5, or switch the checksum algorithm to SHA-256","Smoke-test MessageDigest providers after JVM changes"],"tags":["kettle","udjc","checksum","md5","jvm"],"backgroundTag":"checksum-mismatch","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}