quarkusio/quarkus · critical · UncheckedIOException

Failed to write Windows ${configFile.toAbsolutePath()}

Error message

Failed to write Windows ${configFile.toAbsolutePath()}

What it means

When running Windows-native AWT headless in a container/native-image, the Quarkus AWT extension generates a minimal Windows font configuration file pointing at system font files (e.g. ARIAL.TTF, TIMESBI.TTF). If writing that file fails with an IOException, the code wraps it in an UncheckedIOException with this message. It means the fontconfig bootstrap for the JDK could not be created, so headless graphics/font rendering cannot proceed.

Source

Thrown at extensions/awt/runtime/src/main/java/io/quarkus/awt/runtime/JDKSubstitutions.java:146

                        // Windows is case insensitive, doesn't matter.
                        "filename.Arial=ARIAL.TTF\n" +
                        "filename.Arial_Bold=ARIALBD.TTF\n" +
                        "filename.Arial_Italic=ARIALI.TTF\n" +
                        "filename.Arial_Bold_Italic=ARIALBI.TTF\n" +
                        "filename.Courier_New=COUR.TTF\n" +
                        "filename.Courier_New_Bold=COURBD.TTF\n" +
                        "filename.Courier_New_Italic=COURI.TTF\n" +
                        "filename.Courier_New_Bold_Italic=COURBI.TTF\n" +
                        "filename.Times_New_Roman=TIMES.TTF\n" +
                        "filename.Times_New_Roman_Bold=TIMESBD.TTF\n" +
                        "filename.Times_New_Roman_Italic=TIMESI.TTF\n" +
                        "filename.Times_New_Roman_Bold_Italic=TIMESBI.TTF\n" +
                        "filename.Symbol=SYMBOL.TTF\n" +
                        "filename.Wingdings=WINGDING.TTF\n";
                Files.writeString(configFile, minimalConfig, StandardCharsets.UTF_8);
            }
        } catch (IOException e) {
            throw new UncheckedIOException("Failed to write Windows " + configFile.toAbsolutePath(), e);
        }
    }
}

/**
 * Cut the dependency on Swing and Printing - we support server side, headless mode.
 * TODO: If an extension in Quarkiverse complains, we revisit it here.
 */
@TargetClass(className = "sun.awt.windows.WToolkit", onlyWith = IsWindows.class)
final class Target_sun_awt_windows_WToolkit {

    @Substitute
    public PrintJob getPrintJob(Frame frame, String jobtitle, Properties props) {
        throw new UnsupportedOperationException("Printing is not supported with Quarkus AWT extension.");
    }

    @Substitute
    public PrintJob getPrintJob(Frame frame, String jobtitle, JobAttributes jobAttributes, PageAttributes pageAttributes) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Verify the temp/working directory used for the generated fontconfig file is writable by the process user
  2. Check disk space and permissions on the target path shown in the error message
  3. Ensure no security policy or antivirus blocks java.nio.file.Files.writeString in that directory
  4. Pin to a JDK version where the substitution applies cleanly; report the issue on quarkus-awt if it persists

Example fix

// before: failing due to read-only temp
Files.writeString(configFile, minimalConfig, StandardCharsets.UTF_8);
// after: point java.io.tmpdir at a writable location
// JVM args: -Djava.io.tmpdir=C:\\writable\\tmp
Files.writeString(configFile, minimalConfig, StandardCharsets.UTF_8);
Defensive patterns

Strategy: try-catch

Validate before calling

Path tmp = Paths.get(System.getProperty("java.io.tmpdir"));
if (!Files.isWritable(tmp)) throw new IllegalStateException("temp dir not writable: " + tmp);

Type guard

static boolean isWritableDir(Path p) {
  return p != null && Files.isDirectory(p) && Files.isWritable(p);
}

Try / catch

try {
  awtFontOperation();
} catch (UncheckedIOException e) {
  if (e.getMessage().startsWith("Failed to write Windows")) {
    // fix tmpdir permissions/disk and retry
  }
}

Prevention

When it happens

Trigger: Calling any AWT/font-metric API (e.g. FontMetrics, BufferedImage drawing, PDF image generation with fonts) on a Windows target where JDKSubstitutions.setOsNameAndVersion runs and Files.writeString of the temporary fontconfig file throws IOException — typically due to a read-only filesystem, missing temp directory, or disk full.

Common situations: Windows containers with read-only C: drive or restricted temp dirs; native-image Windows builds where the working/temp path is not writable; disk-quota exhaustion; antivirus blocking file creation.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/b98ff47aaba1cc1a. Report an issue: GitHub.