apache/cassandra · error · RuntimeException

Couldn't write stats html.

Error message

Couldn't write stats html.

What it means

StressGraph.generateGraph wraps IOExceptions from writing the final HTML report (opening the writer, writing, or closing) into a RuntimeException 'Couldn't write stats html.' It is thrown after substituting the computed stats block into the graph HTML template. The underlying IOException cause is dropped, hiding whether it was a permission issue, missing directory, or disk-full condition.

Solutions

  1. Check the output directory exists and is writable by the user running cassandra-stress.
  2. Free disk space or resolve quota/permission issues on the target filesystem.
  3. Write the report to a different, writable location and rerun the graph step.
  4. Patch the catch to include the target file and the cause: new RuntimeException("Couldn't write stats html: " + htmlFile, e).

Example fix

// before
catch (IOException e)
{
    throw new RuntimeException("Couldn't write stats html.");
}
// after
catch (IOException e)
{
    throw new RuntimeException("Couldn't write stats html: " + htmlFile, e);
}
Defensive patterns

Strategy: validation

Validate before calling

java.io.File out = htmlFile; if (out == null || out.getParentFile() == null || !out.getParentFile().isDirectory() || !out.getParentFile().canWrite()) throw new IllegalArgumentException("Cannot write graph html to: " + out);

Try / catch

try { generateGraph(); } catch (RuntimeException e) { if (e.getMessage().contains("Couldn't write stats html")) System.err.println("Check output dir permissions/disk space"); throw e; }

Prevention

When it happens

Trigger: Calling generateGraph (via the stress graph option) when the output html file cannot be created or written: unwritable directory, read-only filesystem, invalid path, or an I/O error mid-write (out.write(html) / out.close()).

Common situations: Writing the graph into a directory that does not exist; running the stress tool as a user without write access to the output location; disk quota exceeded on CI machines; output path on a read-only mount.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/f5834e3767fd21e7. Report an issue: GitHub.

Appendix: source

Thrown at tools/stress/src/org/apache/cassandra/stress/StressGraph.java:96

            }
            stats = this.createJSONStats(stats);
        }
        else
        {
            stats = this.createJSONStats(null);
        }

        try
        {
            PrintWriter out = new PrintWriter(htmlFile);
            String statsBlock = "/* stats start */\nstats = " + JsonUtils.writeAsJsonString(stats) + ";\n/* stats end */\n";
            String html = getGraphHTML().replaceFirst("/\\* stats start \\*/\n\n/\\* stats end \\*/\n", statsBlock);
            out.write(html);
            out.close();
        }
        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);
        }
    }

View on GitHub (pinned to 88fd0f6a0e)