apache/cassandra · error · RuntimeException
Couldn't parser stats json
Error message
Couldn't parser stats json: %s
What it means
StressGraph.parseExistingStats extracts the embedded 'stats = {...};' JSON from an existing graph HTML and parses it with Jackson's readTree; a parse failure (malformed or missing JSON) is rethrown as RuntimeException "Couldn't parser stats json: <message>". This indicates the previous report HTML was truncated, hand-edited, or generated by an incompatible version whose stats block format differs.
Solutions
- Open the HTML and check the content between '/* stats start */' and '/* stats end */' is valid JSON ending in ';'.
- Regenerate the graph from the original stress log instead of loading the corrupted HTML.
- Use matching versions of the stress tool for generating and re-graphing reports.
- Keep the cause in the thrown exception (already present: e) and include the source file in the message for diagnosability.
Example fix
// before
throw new RuntimeException("Couldn't parser stats json: "+e.getMessage(), e);
// after
throw new RuntimeException("Couldn't parse stats json from existing html: " + e.getMessage(), e); Defensive patterns
Strategy: try-catch
Validate before calling
String html = new String(Files.readAllBytes(htmlPath), StandardCharsets.UTF_8); if (!html.contains("/* stats start */") || !html.contains("/* stats end */")) throw new IllegalStateException("No valid stats block in existing html; regenerate the graph"); Try / catch
try { graph.generate(); } catch (RuntimeException e) { if (e.getMessage() != null && e.getMessage().startsWith("Couldn't parser stats json")) { System.err.println("Existing report corrupt; regenerating from log"); graph.generateFromLog(); } else throw e; } Prevention
- Never hand-edit the stats block inside generated HTML.
- Let stress runs complete so the HTML is not truncated mid-write.
- Regenerate reports with the same stress version that produced them.
When it happens
Trigger: generateGraph loads an existing HTML file whose /* stats start */ ... /* stats end */ block either does not match the regex (empty/absent group(1)) or contains invalid JSON, causing IOException from JSON_OBJECT_MAPPER.readTree(matcher.group(1)).
Common situations: A previous stress run was killed mid-write leaving a truncated stats block; the HTML was manually edited; upgrading cassandra-stress across versions changed the JSON schema; copying the HTML through a tool that mangled the embedded script.
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.
Related errors
- Could not decode JSON string as a map
- A CQL blob string must have an even length (since one byte…
- An hex string representing bytes must have an even length
- can't interpret %r as a date with format
- Cannot parse 16-bits int value from
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/4ba886f51e78dd23.
Report an issue: GitHub.
Appendix: source
Thrown at tools/stress/src/org/apache/cassandra/stress/StressGraph.java:111
}
catch (IOException e)
{
throw new RuntimeException("Couldn't write stats html.");
}
}
private ObjectNode parseExistingStats(String html)
{
Pattern pattern = Pattern.compile("(?s).*/\\* stats start \\*/\\nstats = (.*);\\n/\\* stats end \\*/.*");
Matcher matcher = pattern.matcher(html);
matcher.matches();
try
{
return (ObjectNode) JsonUtils.JSON_OBJECT_MAPPER.readTree(matcher.group(1));
}
catch (IOException e)
{
throw new RuntimeException("Couldn't parser stats json: "+e.getMessage(), e);
}
}
private String getGraphHTML()
{
try (InputStream graphHTMLRes = StressGraph.class.getClassLoader().getResourceAsStream("org/apache/cassandra/stress/graph/graph.html"))
{
return new String(ByteStreams.toByteArray(graphHTMLRes));
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
/** Parse log and append to stats array */
private ArrayNode parseLogStats(InputStream log, ArrayNode stats) {
BufferedReader reader = new BufferedReader(new InputStreamReader(log));View on GitHub (pinned to 88fd0f6a0e)