quarkusio/quarkus · error · UnsupportedOperationException
It's not possible to compile H2 triggers when embedding the
Error message
It's not possible to compile H2 triggers when embedding the engine in GraalVM native images
What it means
Quarkus substitutes H2's Database.getCompiler with a stub in NoCompiledTriggersSupport that always throws UnsupportedOperationException in native images. This is the top-level guard: any H2 code path requesting the SourceCompiler for compiled triggers fails immediately, because generating/loading trigger classes at runtime cannot work in a GraalVM native image.
Source
Thrown at extensions/jdbc/jdbc-h2/runtime/src/main/java/io/quarkus/jdbc/h2/runtime/graalvm/NoCompiledTriggersSupport.java:14
package io.quarkus.jdbc.h2.runtime.graalvm;
import org.h2.engine.Database;
import org.h2.util.SourceCompiler;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
@TargetClass(Database.class)
public final class NoCompiledTriggersSupport {
@Substitute
public SourceCompiler getCompiler() {
throw new UnsupportedOperationException(
"It's not possible to compile H2 triggers when embedding the engine in GraalVM native images");
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Rewrite compiled triggers as plain SQL triggers.
- Skip compiled-trigger DDL in native mode via profile-specific migration locations.
- Use JVM mode for workloads requiring compiled H2 triggers.
- Move trigger logic into application code (entity listeners, services).
Example fix
// before -- V2__java_trigger.sql CREATE TRIGGER t BEFORE INSERT ON logs FOR EACH ROW AS $JAVA_SOURCE$ ... $ // after -- V2__sql_trigger.sql CREATE TRIGGER t BEFORE INSERT ON logs FOR EACH ROW SET NEW.created = CURRENT_TIMESTAMP;
Defensive patterns
Strategy: fallback
Validate before calling
boolean avoidCompiledTriggers = ImageInfo.inImageRuntimeCode();
Try / catch
try { db.runMigration(); } catch (UnsupportedOperationException e) { /* H2 compiled triggers not available in native image */ } Prevention
- CI: run at least one native-image test executing all migrations
- Grep migrations for '$JAVA_SOURCE$' before enabling native builds
- Keep dev/test DB behavior identical to native prod (SQL-only triggers)
- Prefer PostgreSQL via Testcontainers when triggers are essential
When it happens
Trigger: H2's engine calling Database.getCompiler() to obtain a compiler for a CREATE TRIGGER ... AS $JAVA_SOURCE$ statement executed in a native image; the @Substitute at NoCompiledTriggersSupport.java:14 throws unconditionally.
Common situations: Startup migrations (Flyway/Liquibase) defining Java-source triggers; JVM-mode dev environment working while the native production build fails on first DDL or trigger-related statement.
Related errors
- It's not possible to compile H2 triggers when embedding the
- Cannot parse version from output: ${stringOutput}
- Not Implemented in native mode
- Unable to create new instance for ${clazz}
- .pfa font files are not supported. Use TrueType fonts, i.e.
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/6e4927abe8563f82.
Report an issue: GitHub.