karatelabs/karate · error · TemplateProcessingException
karate-markup does not support param lists in th:fragment…
Error message
karate-markup does not support param lists in th:fragment signatures.\n Found th:fragment="${value}"\n Change th:fragment="name(p1, p2)" ➜ th:fragment="name"\n Pass values via th:with at the call site; ... What it means
karate-markup does not implement parameterized fragment signatures. When a `th:fragment` attribute value contains a parenthesized parameter list (e.g. `th:fragment="card(title, items)"`), KaFragmentProcessor rejects it via TemplateProcessingException carrying FragmentSupport.signatureMessage, which explains the unsupported syntax and the workaround: declare the fragment without parameters and pass values via `th:with` at the call site.
Solutions
- Change the declaration from `th:fragment="name(p1, p2)"` to just `th:fragment="name"`.
- At the call site, pass the values via `th:with="p1=..., p2=..."` instead of signature arguments.
- Inside the fragment, read the values through `context.get('p1', defaultValue)` for optional fragment params.
- Search your templates for `th:fragment="` occurrences containing `(` and fix all of them — the error is raised per-fragment on render.
Example fix
// before
<div th:fragment="card(title, body)">...</div>
<div th:replace="~{frag :: card('Hi', 'Text')}"></div>
// after
<div th:fragment="card">...</div>
<div th:replace="~{frag :: card}" th:with="title='Hi', body='Text'"></div> Defensive patterns
Strategy: validation
Validate before calling
// Fail fast in tests if any fragment declares params
Files.walk(templatesDir)
.filter(p -> p.toString().endsWith(".html"))
.forEach(p -> {
String s = Files.readString(p);
Matcher m = Pattern.compile("th:fragment=\"([^\"]*\\()[^\"]*\"").matcher(s);
if (m.find()) throw new IllegalStateException("Param list in th:fragment in " + p);
}); Try / catch
try {
render(template);
} catch (TemplateProcessingException e) {
if (e.getMessage() != null && e.getMessage().contains("param lists")) {
log.error("Fragment uses unsupported signature: {}", e.getMessage());
}
throw e;
} Prevention
- Never write th:fragment="name(p1,p2)" — declare just the name
- Pass fragment values with th:with at the call site
- Read optional params inside fragments via context.get('p1', default)
- When migrating from standard Thymeleaf, audit fragment signatures first
When it happens
Trigger: Declaring a fragment as `th:fragment="name(p1, p2)"` — i.e. any th:fragment value containing `(` — then rendering a template that includes it.
Common situations: Migrating templates from full Thymeleaf (which supports `th:fragment="name(p1,p2)"` signatures and `th:replace="~{::frag(...)}"` calls) into Karate markup; copying standard Thymeleaf layout examples from tutorials or the Thymeleaf docs.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- karate-markup does not support param lists in th:fragment…
- ka:dispatch requires an event name; got
- th:each requires `name : expression` form
- context.get() requires a name argument
- ka:data requires format 'varName:expression', got
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/880d98b3e8c63157.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/markup/KaFragmentProcessor.java:67
* check.
*/
final class KaFragmentProcessor extends AbstractElementTagProcessor {
KaFragmentProcessor(TemplateMode templateMode, String dialectPrefix) {
super(templateMode, dialectPrefix, null, false,
StandardFragmentTagProcessor.ATTR_NAME, true,
StandardFragmentTagProcessor.PRECEDENCE);
}
@Override
protected void doProcess(
ITemplateContext context,
IProcessableElementTag tag,
IElementTagStructureHandler structureHandler) {
AttributeName attributeName = getMatchingAttributeName().getMatchingAttributeName();
String value = tag.getAttributeValue(attributeName);
if (value != null && value.indexOf('(') >= 0) {
throw new TemplateProcessingException(
FragmentSupport.signatureMessage(value, null, null));
}
// Marker attribute — strip it now that the validation is done.
structureHandler.removeAttribute(attributeName);
}
}
View on GitHub (pinned to a22eb90246)