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

  1. Rewrite compiled triggers as plain SQL triggers.
  2. Skip compiled-trigger DDL in native mode via profile-specific migration locations.
  3. Use JVM mode for workloads requiring compiled H2 triggers.
  4. 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

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


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