{"record":{"id":"4bd4c26c399e6066","repo":"pentaho/pentaho-kettle","slug":"unexpected-error-trying-to-decode-object","errorCode":null,"errorMessage":"Unexpected error trying to decode object.","messagePattern":"Unexpected error trying to decode object\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"engine-ext/api/src/main/java/org/pentaho/di/engine/api/remote/EncodeUtil.java","lineNumber":60,"sourceCode":"    if ( string == null || string.isEmpty() ) {\n      return new byte[0];\n    }\n\n    ByteArrayOutputStream baos = new ByteArrayOutputStream();\n    // base 64 decode\n    byte[] bytes64 = org.apache.commons.codec.binary.Base64.decodeBase64( string.getBytes(  ) );\n    ByteArrayInputStream zip = new ByteArrayInputStream( bytes64 );\n\n    try (\n      GZIPInputStream unzip = new GZIPInputStream( zip, ZIP_BUFFER_SIZE );\n      BufferedInputStream in = new BufferedInputStream( unzip, ZIP_BUFFER_SIZE );\n    ) {\n      byte[] buff = new byte[ ZIP_BUFFER_SIZE ];\n      for ( int length = 0; ( length = in.read( buff ) ) > 0; ) {\n        baos.write( buff, 0, length );\n      }\n    } catch ( Exception e ) {\n      throw new RuntimeException( \"Unexpected error trying to decode object.\", e );\n    }\n\n    return baos.toByteArray();\n  }\n\n  /**\n   * Base64 encodes then zips a byte array into a compressed string\n   *\n   * @param src the source byte array\n   * @return a compressed, base64 encoded string\n   * @throws IOException\n   */\n  public static String encodeBase64Zipped( byte[] src ) throws IOException {\n    ByteArrayOutputStream baos = new ByteArrayOutputStream( 1024 );\n    try ( Base64OutputStream base64OutputStream = new Base64OutputStream( baos );\n          GZIPOutputStream gzos = new GZIPOutputStream( base64OutputStream ) ) {\n      gzos.write( src );\n    }","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine-ext/api/src/main/java/org/pentaho/di/engine/api/remote/EncodeUtil.java#L42-L78","documentation":"EncodeUtil.decodeBase64Zipped decodes a Base64 string, inflates it with GZIP, and returns the raw serialized bytes. Any failure during Base64 decoding, GZIP inflation, or stream reading is wrapped in this RuntimeException because the utility has no checked-exception contract.","triggerScenarios":"Calling EncodeUtil.decodeBase64Zipped(String) with a string that is not valid Base64, is not GZIP-compressed (missing 0x1f8b magic header), or is truncated/corrupted in transit.","commonSituations":"WebSocket message payloads mangled by an intermediary or proxy; decoding data that was produced without GZIP compression; truncated Base64 from cutting a payload at a length limit; copy-paste dropping trailing characters.","solutions":["Verify the payload was produced by the matching EncodeUtil.encodeBase64Zipped and passed through unmodified.","Check whether a proxy/gateway or WebSocket frame limit truncates or re-encodes the payload.","Decode manually with Base64.getDecoder() and a GZIPInputStream to see which stage fails and get a clearer error.","Log the first/last few bytes of the Base64 string to confirm corruption vs. wrong encoding."],"exampleFix":"// before\nbyte[] data = EncodeUtil.decodeBase64Zipped(untrustedString);\n// after\nString b64 = untrustedString.trim();\nif (!b64.isEmpty() && java.util.Arrays.equals(\n    java.util.Base64.getDecoder().decode(b64.substring(0, Math.min(2, b64.length() * 4 / 3 + 4))),\n    new byte[]{(byte)0x1f, (byte)0x8b})) {\n  byte[] data = EncodeUtil.decodeBase64Zipped(b64);\n} else {\n  throw new IllegalArgumentException(\"payload is not gzip/base64 from encodeBase64Zipped\");\n}","handlingStrategy":"try-catch","validationCode":"if (payload == null || payload.trim().isEmpty()) throw new IllegalArgumentException(\"empty base64 payload\");\nbyte[] raw = java.util.Base64.getDecoder().decode(payload.trim()); // throws early on bad base64\nif (raw.length < 2 || raw[0] != 0x1f || raw[1] != (byte)0x8b) throw new IllegalArgumentException(\"payload is not gzip data\");","typeGuard":null,"tryCatchPattern":"try {\n  byte[] data = EncodeUtil.decodeBase64Zipped(payload);\n} catch (RuntimeException e) {\n  logger.error(\"decodeBase64Zipped failed: \" + e.getCause(), e);\n  throw new IllegalArgumentException(\"Corrupt or non-gzip base64 payload\", e);\n}","preventionTips":["Always pair decodeBase64Zipped with encodeBase64Zipped from the same library version.","Verify payload integrity (length checks, checksums) when passing through proxies or message brokers.","Pre-trim whitespace/newlines from Base64 strings before decoding."],"tags":["base64","gzip","serialization","websocket"],"backgroundTag":"invalid-argument-format","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"}