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

  1. Inspect the chained cause for the underlying generator failure
  2. Verify the TableMetadata instance is well-formed (reload it from the catalog/metadata file)
  3. Report upstream if a valid metadata object fails to serialize — likely a parser bug
  4. 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

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/de99c0e555c67f20. Report an issue: GitHub.