quarkusio/quarkus · error · RuntimeException
Invalid external URL, can not be empty
Error message
Invalid external URL, can not be empty
What it means
ExternalPageBuilder.url(String, String) validates that the external page URL is non-null and non-empty before storing it as the EXTERNAL_URL metadata. An external Dev UI page is by definition a link to some URL; an empty one cannot be rendered.
Source
Thrown at extensions/devui/deployment-spi/src/main/java/io/quarkus/devui/spi/page/ExternalPageBuilder.java:35
public static final String MIME_TYPE_HTML = "text/html";
public static final String MIME_TYPE_JSON = "application/json";
public static final String MIME_TYPE_YAML = "application/yaml";
public static final String MIME_TYPE_PDF = "application/pdf";
protected ExternalPageBuilder(String title) {
super();
super.title = title;
super.componentLink = QWC_EXTERNAL_PAGE_JS;
super.internalComponent = true;// As external page runs on "internal" namespace
}
public ExternalPageBuilder url(String url) {
return url(url, null);
}
public ExternalPageBuilder url(String url, String externalLink) {
if (url == null || url.isEmpty()) {
throw new RuntimeException("Invalid external URL, can not be empty");
}
super.metadata.put(EXTERNAL_URL, url);
if (externalLink != null) {
return staticLabel("<a style='color: var(--lumo-contrast-80pct);' href='" + externalLink
+ "' target='_blank'><vaadin-icon class='icon' icon='font-awesome-solid:up-right-from-square'></vaadin-icon></a>");
}
return this;
}
@SuppressWarnings("unchecked")
public ExternalPageBuilder dynamicUrlJsonRPCMethodName(String methodName) {
if (methodName == null || methodName.isEmpty()) {
throw new RuntimeException("Invalid dynamic URL Method name, can not be empty");
}
super.metadata.put(DYNAMIC_URL, methodName);
return this;
}
View on GitHub (pinned to e1c734241f)
Solutions
- Pass a concrete absolute or app-relative URL, e.g. externalPage().url("https://grafana.example.com/dashboard")
- If the URL comes from config, validate/default it before building: url(cfg.url().isEmpty() ? DEFAULT_URL : cfg.url())
- Skip registering the external page when the configured URL is absent instead of building it with an empty value
- Check for leading/trailing whitespace-only values — normalize with strip() first
Example fix
// before
String url = config.dashboardUrl(); // ""
externalPage().url(url); // throws
// after
String url = config.dashboardUrl();
if (url != null && !url.isBlank()) {
externalPage().url(url);
} Defensive patterns
Strategy: validation
Validate before calling
if (url == null || url.isBlank()) {
throw new IllegalStateException("External page URL must be non-empty before calling url()");
} Type guard
boolean isUsableUrl(String u) {
return u != null && !u.isBlank() && (u.startsWith("http://") || u.startsWith("https://") || u.startsWith("/"));
} Try / catch
try {
externalPage().url(u);
} catch (RuntimeException e) {
if (e.getMessage().contains("Invalid external URL")) {
log.warnf("Skipping external page, url empty");
} else throw e;
} Prevention
- Validate configured URLs with isBlank() before building Dev UI pages
- Skip page registration when the configured URL is absent
- Normalize URLs (strip whitespace) before passing them
- Keep defaults for optional external links in one constants class
When it happens
Trigger: Calling externalPage().url("") or url(null) directly, or via the one-arg url(String) overload which delegates with a null externalLink.
Common situations: URL loaded from configuration (application.properties/env) that is missing or empty when building Dev UI pages at deployment time; template strings interpolated from config keys that were never set; typos so the variable holding the URL is a different, empty one.
Related errors
- Invalid dynamic URL Method name, can not be empty
- Invalid mimeType, can not be empty
- You have to specify a key. This is the key the user will pre
- You have to specify a description. This is what the user wil
- You have to specify userMessage that will be send to AI, or
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/f8b8bd0bbc72408c.
Report an issue: GitHub.