karatelabs/karate · warning

Failed to copy ext assets for

Error message

Failed to copy ext assets for '{}': {}

What it means

copyExtAssets() copies each registered ReportAssets bundle (custom JS/CSS assets contributed for the report) into <outputDir>/ext/<name>. Per-asset failures are caught individually and logged, so one broken asset does not prevent other report output.

Solutions

  1. Confirm the ReportAssets source files are on the classpath and not filtered out by the build
  2. Check that <outputDir>/ext is creatable/writable and no file occupies a needed directory path
  3. Validate assets.name() contains only safe path characters
  4. Enable debug logging or run a minimal suite to isolate which asset fails
Defensive patterns

Strategy: try-catch

Validate before calling

for (ReportAssets a : reportAssets.values()) {
    if (getClass().getResource(a.classpathSource()) == null)
        logger.warn("ext asset missing from classpath: {}", a.name());
}
if (!Files.isWritable(outputDir)) throw new IllegalStateException("output dir not writable");

Try / catch

try {
    assets.copyTo(outputDir.resolve("ext").resolve(assets.name()));
} catch (Exception e) {
    logger.warn("Failed to copy ext assets for '{}': {}", assets.name(), e.getMessage(), e);
}

Prevention

When it happens

Trigger: Exception from assets.copyTo(outputDir.resolve("ext").resolve(assets.name())) during writeSummaryPages — asset source files missing from the classpath, target directory not writable, or name/path conflicts in the ext folder.

Common situations: Custom report assets registered via an extension but packaged incorrectly (excluded from the jar); read-only output directory; file name from assets.name() colliding with a directory or containing invalid path characters.

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 karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/dcf625147d682f03. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/output/HtmlReportWriter.java:617

        return s.replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;");
    }

    /**
     * Copy each registered ext's declared assets into {@code outputDir/ext/<name>/}.
     * Best-effort per ext: a copy failure for one ext is logged and the rest proceed.
     */
    private static void copyExtAssets(Map<String, ReportAssets> reportAssets, Path outputDir) {
        if (reportAssets == null || reportAssets.isEmpty()) {
            return;
        }
        for (ReportAssets assets : reportAssets.values()) {
            try {
                assets.copyTo(outputDir.resolve("ext").resolve(assets.name()));
            } catch (Exception e) {
                logger.warn("Failed to copy ext assets for '{}': {}", assets.name(), e.getMessage());
            }
        }
    }

    // ========== Template and Resource Loading ==========

    private static String loadTemplate(String name) throws IOException {
        return loadClasspathResource(RESOURCE_ROOT + name, true);
    }

    /**
     * Read a UTF-8 classpath resource. When {@code required} is true a missing
     * resource raises; otherwise the empty string is returned.
     */
    private static String loadClasspathResource(String path, boolean required) throws IOException {
        try (InputStream is = HtmlReportWriter.class.getClassLoader().getResourceAsStream(path)) {
            if (is == null) {
                if (required) {

View on GitHub (pinned to a22eb90246)