Diagnosing Thymeleaf th:if Conditional Rendering Failures
When a th:if element stays hidden despite a non‑null model value, the cause is usually a null‑sensitive OGNL/SpEL expression or a global setting that forces null checks.
01 Aug 2026, 19:44 UTC

Recognizable Symptom
During page rendering a fragment that should be displayed only when a model attribute is present never appears, even though the controller sets the attribute to a non‑null object. The element remains absent in the browser, and no server error is logged.
Typical Diagnostic Table
| Symptom | Likely Cause | Quick Check |
|---|---|---|
| th:if element never rendered | Referenced bean property is null or misspelled | Inspect model attribute in controller or logs |
| Element appears only intermittently | Type mismatch (e.g., string vs number) in expression | Print value type in a debug log |
| All th:if elements hidden | spring.el.allow-null-access disabled globally | Check Thymeleaf configuration |
Step‑by‑Step Checks
- Confirm the model attribute exists and is non‑null.
- Run the application and set a breakpoint in the controller where the attribute is added.
- Inspect the variable in the debugger; verify it is not null.
- If using Spring Boot, add `System.out.println(\"user=\"+user);` before returning the view.
- Validate the OGNL/SpEL expression syntax.
- Open the HTML file and locate the th:if attribute.
- Copy the expression (e.g., #{user.name}) into a temporary Thymeleaf test page or a unit test.
- Use the Thymeleaf parser (`org.thymeleaf.TemplateEngine`) to evaluate the expression with a mock model.
- Check bean property type and getter return value.
- Ensure the Java bean follows JavaBeans conventions: a private field, a public getter returning the same type.
- If the property is a wrapper (e.g., Integer), verify that the getter returns an object, not a primitive, unless the expression handles nulls.
- Inspect the global spring.el.allow-null-access setting.
- Locate `application.properties` or `application.yml`.
- Look for `spring.el.allow-null-access=false` or a custom `ThymeleafConfigurer`.
- If the property is set to false, null values are treated as false, causing th:if to hide elements.
- Temporarily replace th:if with a literal null‑check.
- Change `` to ``.
- Refresh the page; if the element now appears, the original expression was the issue.
Fixes Aligned with Findings
- If the model attribute is missing or misspelled, add it to the model in the controller:\n
model.addAttribute(\"user\", user); - Correct the expression spelling:\n
→#\\{user.nmae\\}#{user.name}. - Handle type mismatches by converting types or using explicit conversion:\n
or ensure the getter returns#{String.valueOf(user.age)}Stringwhen compared to a string. - Enable null‑access checks:\n
in configuration, then restart.spring.el.allow-null-access=true - Simplify complex expressions to avoid performance degradation:\n
#{user.name != null}instead of nested property accesses.
Escalation Criteria
If after verifying the model, expression syntax, type, and global setting the element is still hidden, consider the following escalation path:
- Profile the view rendering time with a tool such as VisualVM or the Spring Boot Actuator metrics; excessive OGNL evaluation may indicate a performance bottleneck.
- Review nested th:if statements for overriding logic; rewrite to use a single condition or a helper utility bean that returns the final boolean.
- If the issue persists, open a bug report with a minimal reproducible example, including the exact HTML fragment, the bean definition, and the Spring Boot version.
Practical Verification After Fix
- Re‑run the page in a browser, open the developer console, and confirm the element appears when the model attribute is set to a non‑null value.
- Check the server logs for any Thymeleaf parsing warnings; they should be absent after the fix.
- If using automated tests, assert that the rendered HTML contains the expected element (`assertThat(html).contains(\"Welcome\")`).
Limitation: Disabling spring.el.allow-null-access forces null checks to be true, which may expose hidden elements but also changes the behavior of all th:if expressions in the application. Test in a staging environment before applying to production.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.