karatelabs/karate · warning

Failed to create JUnit XML output directory

Error message

Failed to create JUnit XML output directory: {}

What it means

JunitXmlReportListener.onSuiteStart() eagerly creates the JUnit XML output directory so later per-feature writes succeed. If directory creation fails, the listener warns and continues; subsequent per-feature XML writes may then also fail.

Solutions

  1. Fix the outputDir configuration so it points to a writable, non-existent-or-directory path
  2. Pre-create the parent directories manually or fix permissions (chown/chmod) for the process user
  3. Check the path is not occupied by a regular file
  4. Verify the volume (e.g. CI workspace mount) is mounted and writable before the suite runs

Example fix

// before
karate.outputDir=target/surefire-reports/karate (parent missing, read-only CI)
// after: ensure parent exists and is writable
mkdir -p target/surefire-reports && chmod u+w target/surefire-reports
Defensive patterns

Strategy: validation

Validate before calling

Path dir = Paths.get(karateOutputDir);
if (Files.exists(dir) && !Files.isDirectory(dir))
    throw new IllegalStateException("outputDir is a file: " + dir);
Files.createDirectories(dir); // fail fast before suite start

Prevention

When it happens

Trigger: Files.createDirectories(outputDir) throwing at suite start — parent path does not exist and cannot be created, permission denied, or the path exists as a regular file.

Common situations: Misconfigured outputDir (typo, points to a file); running CI as a user without write permission on the target volume; network/overlay mounts unavailable at suite start.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/7ce3c63629421fda. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/output/JunitXmlReportListener.java:71

    /**
     * Create a new JUnit XML report listener.
     *
     * @param outputDir the base output directory (subfolder will be created)
     */
    public JunitXmlReportListener(Path outputDir) {
        this.outputDir = outputDir.resolve(SUBFOLDER);
    }

    @Override
    public void onSuiteStart(Suite suite) {
        // Create output directory eagerly
        try {
            if (!Files.exists(outputDir)) {
                Files.createDirectories(outputDir);
            }
        } catch (Exception e) {
            logger.warn("Failed to create JUnit XML output directory: {}", e.getMessage());
        }
    }

    @Override
    public void onFeatureEnd(FeatureResult result) {
        // Sort scenarios for deterministic ordering
        result.sortScenarioResults();

        // Serialize AND write here, on the feature's own thread. The write used to be handed
        // to a single-thread executor with an unbounded queue; measured over a many-feature
        // suite that thread was idle — its share of the work was a few percent of wall-clock —
        // so the queue could only ever grow, never help. Writing inline also means a feature
        // cannot complete until its report is on disk, which bounds what is held in memory.
        try {
            JunitXmlWriter.writeSerialized(JunitXmlWriter.fileNameFor(result),
                    JunitXmlWriter.serializeFeature(result), outputDir);
        } catch (Exception e) {
            logger.warn("Failed to write JUnit XML for {}: {}", result.getDisplayName(), e.getMessage());

View on GitHub (pinned to a22eb90246)