apache/iceberg · error · RuntimeException
Unable to produce hash of table metadata
Error message
Unable to produce hash of table metadata
What it means
HMSTablePropertyHelper.hashOf() throws RuntimeException when it fails to serialize TableMetadata to JSON or compute its SHA-256 hash, e.g. NoSuchAlgorithmException (SHA-256 unavailable) or IOException from the JSON generator/hash writer plumbing.
Solutions
- Use a standard JDK/JCE provider that includes SHA-256
- Inspect the chained cause for the actual serialization/IO problem
- Report/fix if TableMetadataParser.toJson fails on specific metadata content
Example fix
// before
new HashWriter("SHA-256", ...); // NoSuchAlgorithmException
// after
// run on full JDK (e.g. Temurin) where SHA-256 is always available Defensive patterns
Strategy: try-catch
Try / catch
try { /* property update path */ } catch (RuntimeException e) { if (e.getCause() instanceof NoSuchAlgorithmException || e.getCause() instanceof IOException) { /* handle serialization failure */ } } Prevention
- Run on a full JDK with standard JCE providers
- Keep Iceberg version current (parser fixes)
- Surface chained causes in logs
When it happens
Trigger: Computing the metadata hash during table property updates when the JVM lacks the SHA-256 algorithm or the JsonGenerator/HashWriter pipeline throws IOException.
Common situations: Running on a restricted JRE without SHA-256 (rare); I/O errors in the in-memory hash stream; bugs in metadata parser serialization.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- Full metadata integrity check skipped because no metadata…
- The current metadata file
- Cannot call acquireLock twice for
- Cannot call commit on temporary table operations
- Cannot call refresh on temporary table operations
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/f3fb719edaaceae4.
Report an issue: GitHub.
Appendix: source
Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/HMSTablePropertyHelper.java:305
byte[] expectedHashBytes = Base64.getDecoder().decode(metadataHashFromHMS);
if (!Arrays.equals(expectedHashBytes, currentHashBytes)) {
throw new RuntimeException(
String.format(
"The current metadata file %s might have been modified. Hash of metadata loaded from storage differs "
+ "from HMS-stored metadata hash.",
metadata.metadataFileLocation()));
}
}
private static byte[] hashOf(TableMetadata tableMetadata) {
try (HashWriter hashWriter = new HashWriter("SHA-256", StandardCharsets.UTF_8);
JsonGenerator generator = JsonUtil.factory().createGenerator(hashWriter)) {
TableMetadataParser.toJson(tableMetadata, generator);
generator.flush();
return hashWriter.getHash();
} catch (NoSuchAlgorithmException | IOException e) {
throw new RuntimeException("Unable to produce hash of table metadata", e);
}
}
private static void setField(
Map<String, String> parameters, String key, String value, long maxHiveTablePropertySize) {
if (value.length() <= maxHiveTablePropertySize) {
parameters.put(key, value);
} else {
LOG.warn(
"Not exposing {} in HMS since it exceeds {} characters", key, maxHiveTablePropertySize);
}
}
private static boolean exposeInHmsProperties(long maxHiveTablePropertySize) {
return maxHiveTablePropertySize > 0;
}
}
View on GitHub (pinned to 86d9c8fc54)