quarkusio/quarkus · error · IllegalStateException
No suitable template variant found
Error message
No suitable template variant found
What it means
When a mail template is sent, MailTemplateInstanceImpl collects the template variants (e.g. for text/html, text/plain content types) that match the requested content types and locales. If no variant matches — the results list is empty — send() throws IllegalStateException('No suitable template variant found') and no mail is sent.
Source
Thrown at extensions/mailer/runtime/src/main/java/io/quarkus/mailer/runtime/MailTemplateInstanceImpl.java:147
if (variantsAttr != null) {
List<Result> results = new ArrayList<>();
@SuppressWarnings("unchecked")
List<Variant> variants = (List<Variant>) variantsAttr;
for (Variant variant : variants) {
if (variant.getContentType().equals(Variant.TEXT_HTML) || variant.getContentType().equals(Variant.TEXT_PLAIN)) {
results.add(new Result(variant,
Uni.createFrom().completionStage(
new Supplier<CompletionStage<? extends String>>() {
@Override
public CompletionStage<? extends String> get() {
return templateInstance
.setAttribute(TemplateInstance.SELECTED_VARIANT, variant).renderAsync();
}
})));
}
}
if (results.isEmpty()) {
throw new IllegalStateException("No suitable template variant found");
}
List<Uni<String>> unis = results.stream().map(Result::resolve).collect(Collectors.toList());
return Uni.combine().all().unis(unis)
.combinedWith(combine(results))
.chain(new Function<Mail, Uni<? extends Void>>() {
@Override
public Uni<? extends Void> apply(Mail m) {
return mailer.send(m);
}
});
} else {
throw new IllegalStateException("No template variant found");
}
}
private Function<List<?>, Mail> combine(List<Result> results) {
return new Function<List<?>, Mail>() {
@OverrideView on GitHub (pinned to e1c734241f)
Solutions
- Verify template files exist under src/main/resources/templates with correct names and extensions (.html/.txt for Qute)
- Provide both HTML and plain-text variants (or a single variant matching the mail's content types) for the template name used
- Check the locale/content-type selection logic — add a localized variant or send without forcing a locale
- Verify the template name/path string passed to the MailTemplate is correct
Example fix
// before: only templates/mail/welcome.txt exists but mail sent as HTML
mailTemplate.of("mail/welcome").to(to).send(); // IllegalStateException
// after: add src/main/resources/templates/mail/welcome.html (and keep welcome.txt)
mailTemplate.of("mail/welcome").to(to).send(); Defensive patterns
Strategy: validation
Validate before calling
// ensure variants exist for both content types before sending
TemplateInstance instance = mailTemplate.getInjectableTemplateInstance();
if (mailTemplate.data() == null || !templateResourceExists("templates/mail/welcome.html")) {
throw new IllegalStateException("mail template variant missing: add .html and .txt files under templates/");
}
mailTemplate.of("mail/welcome").to(to).send(); Type guard
boolean hasHtmlVariant(String templateName) {
return getClass().getResource("/templates/" + templateName + ".html") != null;
} Try / catch
try {
mailTemplate.of("mail/welcome").to(to).send().await().indefinitely();
} catch (IllegalStateException e) {
if (e.getMessage().contains("No suitable template variant")) {
log.errorf("Template 'mail/welcome' lacks a variant for the requested content type/locale");
}
throw e;
} Prevention
- Ship both .html and .txt variants of every mail template
- Keep template paths under src/main/resources/templates matching the name passed to of()
- Test mail sending (Dev Services mailpit / MailHog) in CI before production
- Avoid forcing locales unless localized variants exist for all of them
When it happens
Trigger: Calling mailTemplate.of("name").to(...).send() where the template exists but none of its variants match the requested content type (e.g. template has only text/plain but mail is sent as HTML) or locale; often when the template name resolves to an empty/blank template with no variants.
Common situations: Typo or wrong directory for template files so only a partial variant loads; using quarkus.mailer.* without defining both HTML and text variants; sending with a locale for which no localized variant exists; template named via config property that is unset.
Related errors
- No template variant found
- Cannot add header, key and value must not be null
- Cannot remove header, key must not be null
- No template resource path specified
- Unable to find credentials provider for the mailer {{mailerN
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ed8f0710d5ae626f.
Report an issue: GitHub.