quarkusio/quarkus · error · RuntimeException

CardAction title is required

Error message

CardAction title is required

What it means

CardActionBuilder.build() validates that a title was supplied before constructing the CardAction. The Dev UI needs a visible label for every card action button/link, so building without one is treated as a programming mistake and fails fast.

Source

Thrown at extensions/devui/deployment-spi/src/main/java/io/quarkus/devui/spi/page/CardActionBuilder.java:49

        this.actionType = CardAction.ActionType.JSONRPC;
        this.actionReference = methodName;
        return this;
    }

    public CardActionBuilder url(String url) {
        this.actionType = CardAction.ActionType.URL;
        this.actionReference = url;
        return this;
    }

    public CardActionBuilder showResultNotification(boolean show) {
        this.showResultNotification = show;
        return this;
    }

    public CardAction build() {
        if (title == null || title.isEmpty()) {
            throw new RuntimeException("CardAction title is required");
        }
        if (actionType == null || actionReference == null || actionReference.isEmpty()) {
            throw new RuntimeException("CardAction requires either jsonRpcMethodName() or url()");
        }
        return new CardAction(title, icon, tooltip,
                actionType, actionReference, showResultNotification);
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call title("Your label") on the CardActionBuilder before build()
  2. If the title comes from config/data, default it, e.g. title(name == null || name.isBlank() ? "Unnamed action" : name)
  3. Chain the builder in one fluent expression starting with title(...) so it cannot be omitted
  4. Add a unit test asserting actions built from your extension always carry a non-empty title

Example fix

// before
CardAction action = new CardActionBuilder()
        .url("https://example.com")
        .build(); // throws
// after
CardAction action = new CardActionBuilder()
        .title("Open dashboard")
        .url("https://example.com")
        .build();
Defensive patterns

Strategy: validation

Validate before calling

if (title == null || title.isBlank()) {
    throw new IllegalStateException("CardAction builder requires a non-empty title");
}

Type guard

boolean hasTitle(CardAction a) {
    return a != null && a.getTitle() != null && !a.getTitle().isEmpty();
}

Try / catch

try {
    return builder.build();
} catch (RuntimeException e) {
    if (e.getMessage().equals("CardAction title is required")) {
        return builder.title("Unnamed action").build();
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling CardActionBuilder.build() after invoking jsonRpcMethodName(...) or url(...) but never calling title("...") (or calling title with null/empty string).

Common situations: Extension authors adding buttons to Dev UI cards via PageBuilder.addCardAction(...) and skipping the title fluent call; copying builder code where the title line was deleted; dynamically generated titles that end up empty (e.g. from a blank config value).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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