quarkusio/quarkus · error · UncheckedIOException
Unable to set tmp java.home for FontConfig Quarkus AWT usage
Error message
Unable to set tmp java.home for FontConfig Quarkus AWT usage in ${javaHome} What it means
On native image, Quarkus AWT's substitution for sun.awt.FontConfiguration (Linux) creates a temporary java.home layout (lib/ and conf/fonts directories) that FontConfig requires. If creating these directories fails with IOException, an UncheckedIOException with this message is thrown, aborting font initialization.
Source
Thrown at extensions/awt/runtime/src/main/java/io/quarkus/awt/runtime/JDKSubstitutions.java:69
*/
@TargetClass(className = "sun.awt.FontConfiguration", onlyWith = IsLinux.class)
final class Target_sun_awt_FontConfiguration_Linux {
@Alias
protected static String osVersion;
@Alias
protected static String osName;
@Substitute
protected void setOsNameAndVersion() {
final Path javaHome = Path.of(System.getProperty("java.io.tmpdir"), "quarkus-awt-tmp-fonts");
try {
System.setProperty("java.home", javaHome.toString());
osName = System.getProperty("os.name", "unknown");
osVersion = System.getProperty("os.version");
Files.createDirectories(javaHome.resolve("lib"));
Files.createDirectories(javaHome.resolve("conf").resolve("fonts"));
} catch (IOException e) {
throw new UncheckedIOException("Unable to set tmp java.home for FontConfig Quarkus AWT usage in " + javaHome, e);
}
}
}
/**
* See Target_sun_awt_FontConfiguration_Linux, for context.
*
* Windows doesn't have fontconfig package and its config file installed like Linux has.
* Java runtime looks for the config file inside our fake JAVA_HOME.
* We provide a skeleton, i18n ignorant version to satisfy the basic headless fonts processing.
*/
@TargetClass(className = "sun.awt.FontConfiguration", onlyWith = IsWindows.class)
final class Target_sun_awt_FontConfiguration_Windows {
@Alias
protected static String osVersion;
@Alias
protected static String osName;
View on GitHub (pinned to e1c734241f)
Solutions
- Ensure the directory backing java.io.tmpdir (or the path reported) is writable by the process user
- Mount a writable tmpfs at /tmp in the container (e.g. docker run --tmpfs /tmp:rw)
- Check disk space and permissions; run the binary with a user that owns its directory
- If java.home was mis-resolved, verify how the native binary locates its temp dir and pass -Djava.io.tmpdir to a writable path
Example fix
// before (read-only rootfs) docker run --read-only myapp-image // after docker run --read-only --tmpfs /tmp:rw,noexec,nosuid myapp-image
Defensive patterns
Strategy: validation
Validate before calling
Path tmp = Path.of(System.getProperty("java.io.tmpdir"));
if (!Files.isWritable(tmp)) {
throw new IllegalStateException("Writable temp dir required for AWT/FontConfig in native mode: " + tmp);
} Try / catch
try {
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
} catch (UncheckedIOException e) {
if (e.getMessage() != null && e.getMessage().contains("Unable to set tmp java.home")) {
log.error("Mount a writable /tmp or grant write access: " + e.getCause());
}
throw e;
} Prevention
- Always provide a writable /tmp (tmpfs) to native containers using AWT
- Check SELinux/AppArmor policies for temp-dir writes in production images
- Verify disk space and user permissions before deploying native binaries
- Warm up font initialization in a startup health check to fail fast
When it happens
Trigger: First AWT/Font usage in a native executable where the temp directory (usually io.tmpdir under the app dir) cannot be created: read-only filesystem, permission denied, or no space.
Common situations: Running the native binary in a read-only container (distroless, read-only /tmp); running as a non-root user without write access; security-hardened runtime blocking directory creation.
Related errors
- .pfa font files are not supported. Use TrueType fonts, i.e.
- .pfb font files are not supported. Use TrueType fonts, i.e.
- Unable to create new instance for ${clazz}
- Failed to write Windows ${configFile.toAbsolutePath()}
- JMX is not available in native images.
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/1d69c587d0c1c6a3.
Report an issue: GitHub.