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
- Confirm the ReportAssets source files are on the classpath and not filtered out by the build
- Check that <outputDir>/ext is creatable/writable and no file occupies a needed directory path
- Validate assets.name() contains only safe path characters
- 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
- Package custom report assets in the jar (verify with jar tf)
- Restrict asset names to filesystem-safe characters
- Check ext/ for stale files or name collisions between runs
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
- ext ' ': resource vanished after validation
- ext ' ': points at missing resource
- ext ' ': failed reading
- Failed to copy static resources
- Failed to write HTML report
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("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("\"", """);
}
/**
* 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)