{"record":{"id":"cd1658db59a20e54","repo":"apache/iceberg","slug":"failed-to-decode-value-as-utf-8-s","errorCode":null,"errorMessage":"Failed to decode value as UTF-8: %s","messagePattern":"Failed to decode value as UTF-8: (.+?)","errorType":"exception","errorClass":"RuntimeIOException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/types/Conversions.java","lineNumber":192,"sourceCode":"      case TIMESTAMP_NANO:\n        if (tmp.remaining() < 8) {\n          // type was later promoted to long\n          return (long) tmp.getInt();\n        }\n        return tmp.getLong();\n      case FLOAT:\n        return tmp.getFloat();\n      case DOUBLE:\n        if (tmp.remaining() < 8) {\n          // type was later promoted to long\n          return (double) tmp.getFloat();\n        }\n        return tmp.getDouble();\n      case STRING:\n        try {\n          return DECODER.get().decode(tmp);\n        } catch (CharacterCodingException e) {\n          throw new RuntimeIOException(e, \"Failed to decode value as UTF-8: %s\", buffer);\n        }\n      case UUID:\n        return UUIDUtil.convert(tmp);\n      case FIXED:\n      case BINARY:\n        return tmp;\n      case DECIMAL:\n        Types.DecimalType decimal = (Types.DecimalType) type;\n        byte[] unscaledBytes = new byte[buffer.remaining()];\n        tmp.get(unscaledBytes);\n        return new BigDecimal(new BigInteger(unscaledBytes), decimal.scale());\n      case VARIANT:\n        return Variant.from(tmp);\n      case GEOMETRY:\n      case GEOGRAPHY:\n        return GeospatialBound.fromByteBuffer(tmp);\n      case UNKNOWN:\n        // underlying type not known","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/types/Conversions.java#L174-L210","documentation":"Conversions.internalFromByteBuffer deserializes binary values per type. For STRING it UTF-8 decodes the buffer; invalid byte sequences (not valid UTF-8) cause CharacterCodingException, wrapped in RuntimeIOException with this message. This typically indicates corrupted or wrongly-encoded data in metadata/statistics.","triggerScenarios":"Calling Conversions.fromByteBuffer(stringType, buffer) where the buffer bytes are not valid UTF-8 (e.g. Latin-1 encoded bytes, truncated multi-byte sequence).","commonSituations":"Reading partition/statistics metadata written by non-Iceberg tools; buffers extracted from files with encoding corruption; manual byte manipulation producing invalid UTF-8.","solutions":["Fix the writer to UTF-8 encode strings per the Iceberg spec and rewrite the data","Decode leniently with a CharsetDecoder using CodingErrorAction.REPLACE on the raw bytes yourself","Catch RuntimeIOException and treat the value as null/unknown rather than failing the read"],"exampleFix":"// before\nString s = (String) Conversions.fromByteBuffer(Types.StringType.get(), badBuffer);\n// after\nString s = new CharsetDecoder(StandardCharsets.UTF_8.newDecoder()\n    .onMalformedInput(CodingErrorAction.REPLACE)).decode(badBuffer.duplicate());","handlingStrategy":"try-catch","validationCode":"CharsetDecoder dec = StandardCharsets.UTF_8.newDecoder().onMalformedInput(CodingErrorAction.REPORT);\ntry { dec.decode(buffer.duplicate()); } catch (CharacterCodingException e) { /* invalid UTF-8 */ }","typeGuard":null,"tryCatchPattern":"try { v = Conversions.fromByteBuffer(type, buf); } catch (RuntimeIOException e) { v = null; /* treat as unknown value */ }","preventionTips":["Ensure writers UTF-8 encode strings per the Iceberg spec","Avoid manual byte manipulation of metadata buffers","Detect corrupted files via checksums before parsing metadata"],"tags":["java","encoding","utf-8","deserialization"],"backgroundTag":"invalid-argument-format","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}