apache/iceberg · error · IllegalArgumentException
Malformed JSON
Error message
Malformed JSON: %s
What it means
SnowflakeTableMetadata.parseJson wraps IOExceptions from Jackson when parsing the metadata JSON string returned by the Snowflake client into IllegalArgumentException with 'Malformed JSON'. This payload comes from Snowflake's GET (system) GET_ICEBERG_TABLE_INFO/metadata API, so a non-JSON response indicates a client/protocol problem rather than bad user data.
Solutions
- Verify Snowflake connectivity and credentials; an error page or empty body usually means auth/session failure upstream of this parse.
- Upgrade the Snowflake JDBC driver and iceberg-snowflake module to matched recent versions so the metadata payload shape is supported.
- Log the raw JSON string from the exception message and inspect it — it reveals what the client actually received (HTML vs truncated JSON).
- Retry the load; transient Snowflake API failures can produce malformed bodies. Add retry with backoff around loadTableMetadata.
Example fix
// before
SnowflakeTableMetadata meta = SnowflakeTableMetadata.parseJson(client.loadTableMetadata(id));
// after
String json = client.loadTableMetadata(id);
if (json == null || !json.trim().startsWith("{")) {
throw new IllegalStateException("Unexpected Snowflake metadata payload: " + json);
}
SnowflakeTableMetadata meta = SnowflakeTableMetadata.parseJson(json); Defensive patterns
Strategy: try-catch
Validate before calling
if (json == null || json.trim().isEmpty() || !(json.trim().startsWith("{") || json.trim().startsWith("["))) {
throw new IllegalStateException("Snowflake metadata payload is not JSON: " + json);
} Try / catch
try { meta = SnowflakeTableMetadata.parseJson(json); } catch (IllegalArgumentException e) { LOG.error("Bad Snowflake metadata payload: {}", json, e); throw new RetryableLoadException(e); } Prevention
- Keep Snowflake JDBC driver and iceberg-snowflake versions current
- Verify Snowflake auth/session health when metadata loads start failing
- Retry transient loads with backoff; log the raw payload for diagnosis
When it happens
Trigger: snowflakeClient.loadTableMetadata returns a string that is not valid JSON (empty string, HTML error page, truncated response, driver-level error text), which readValue fails to parse.
Common situations: Expired or misconfigured Snowflake session returning an error body instead of JSON; older Snowflake JDBC/driver versions returning a different payload shape; network proxies or Snowflake outages injecting non-JSON error pages; programmatic misuse of parseJson with hand-built strings.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- record.value is not valid json for record.value
- Cannot convert identifier
- Cannot convert JSON to literal: " + node
- Cannot convert update requirement to json. Unrecognized type
- Cannot find table
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/e3968902d5de3c57.
Report an issue: GitHub.
Appendix: source
Thrown at snowflake/src/main/java/org/apache/iceberg/snowflake/SnowflakeTableMetadata.java:139
// gcs://bucket/path
// to:
// gs://bucket/path
return "gs" + snowflakeLocation.substring(3);
}
return snowflakeLocation;
}
/**
* Factory method for parsing a JSON string containing expected Snowflake table metadata into a
* SnowflakeTableMetadata object.
*/
public static SnowflakeTableMetadata parseJson(String json) {
JsonNode parsedVal;
try {
parsedVal = JsonUtil.mapper().readValue(json, JsonNode.class);
} catch (IOException ioe) {
throw new IllegalArgumentException(String.format("Malformed JSON: %s", json), ioe);
}
String snowflakeMetadataLocation = JsonUtil.getString("metadataLocation", parsedVal);
String status = JsonUtil.getStringOrNull("status", parsedVal);
String icebergMetadataLocation = snowflakeLocationToIcebergLocation(snowflakeMetadataLocation);
return new SnowflakeTableMetadata(
snowflakeMetadataLocation, icebergMetadataLocation, status, json);
}
}
View on GitHub (pinned to 86d9c8fc54)