apache/iceberg · error · RuntimeIOException
Failed to write json for: %s
Error message
Failed to write json for: %s
What it means
This toJson overload renders TableMetadata to an in-memory String using a StringWriter/JsonGenerator. Although StringWriter never throws real IOExceptions, the Jackson generator API is checked, so failures are wrapped in RuntimeIOException ('Failed to write json for: <metadata>'). In practice this surfaces generator/serialization defects rather than environment problems.
Source
Thrown at core/src/main/java/org/apache/iceberg/TableMetadataParser.java:160
}
public static String getFileExtension(Codec codec) {
return codec.extension + ".metadata.json";
}
public static String getOldFileExtension(Codec codec) {
// we have to be backward-compatible with .metadata.json.gz files
return ".metadata.json" + codec.extension;
}
public static String toJson(TableMetadata metadata) {
try (StringWriter writer = new StringWriter();
JsonGenerator generator = JsonUtil.factory().createGenerator(writer)) {
toJson(metadata, generator);
generator.flush();
return writer.toString();
} catch (IOException e) {
throw new RuntimeIOException(e, "Failed to write json for: %s", metadata);
}
}
@SuppressWarnings("checkstyle:CyclomaticComplexity")
public static void toJson(TableMetadata metadata, JsonGenerator generator) throws IOException {
generator.writeStartObject();
generator.writeNumberField(FORMAT_VERSION, metadata.formatVersion());
generator.writeStringField(TABLE_UUID, metadata.uuid());
if (metadata.location() != null) {
generator.writeStringField(LOCATION, metadata.location());
}
if (metadata.formatVersion() > 1) {
generator.writeNumberField(LAST_SEQUENCE_NUMBER, metadata.lastSequenceNumber());
}
generator.writeNumberField(LAST_UPDATED_MILLIS, metadata.lastUpdatedMillis());
generator.writeNumberField(LAST_COLUMN_ID, metadata.lastColumnId());
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Inspect the chained cause for the underlying generator failure
- Verify the TableMetadata instance is well-formed (reload it from the catalog/metadata file)
- Report upstream if a valid metadata object fails to serialize — likely a parser bug
- As a workaround, round-trip via a file: write with TableMetadataParser.write then re-read
Defensive patterns
Strategy: try-catch
Try / catch
try { String json = TableMetadataParser.toJson(metadata); }
catch (RuntimeIOException e) {
LOG.error("In-memory metadata serialization failed: {}", e.getCause(), e);
} Prevention
- Treat this as a bug signal: in-memory JSON writing has no real I/O
- Report upstream with the metadata object if a valid instance fails
- Keep parser code (TableMetadataParser.toJson overloads) free of invalid writes
- Prefer writing to a file for debugging to also surface real I/O conditions
When it happens
Trigger: Calling TableMetadataParser.toJson(TableMetadata) when JSON generation fails — typically an unexpected internal state in TableMetadata handed to the generator (e.g. malformed nested values), or a bug in a toJson overload writing invalid structures.
Common situations: Debugging/dumping metadata to a string in tools or tests; custom catalogs that serialize metadata themselves; rarely hit in normal commits since string rendering is memory-only.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- Cannot convert update requirement to json. Unrecognized type
- Unrecognized update requirement. Cannot convert to json: %s
- Unsupported task type:
- Cannot write unknown type:
- does not have a metadata file location
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/de99c0e555c67f20.
Report an issue: GitHub.