Skip to content

Error responses and stack traces

Severity: mediumApplies to: Spring Boot 2.x+Applies to: Spring Boot 4.1Facts last verified 2026-08-09 against Spring Boot 4.1.0

Read straight from ErrorProperties.java:

private IncludeAttribute includeStacktrace = IncludeAttribute.NEVER;
private IncludeAttribute includeMessage = IncludeAttribute.NEVER;

Both default to NEVER. Spring Boot’s default error response carries a timestamp, status, error name and path — and no stack trace, and not even the exception message.

That makes this a verify page, and it is worth stating plainly because it is the one place where Spring Boot’s defaults are better than both of its neighbours on this site:

Framework Default on an unhandled error
Spring Boot status only — no trace, no message
Django full debug page if DEBUG=True (default False)
Express err.stack to the client, because NODE_ENV defaults to development

If you are on Boot 4.x these live under spring.web.error.*. On 3.x they are server.error.*. Verified by diffing the application-properties appendix across versions on 2026-08-09:

Appendix server.error.* spring.web.error.*
Boot 3.5.9 7 entries none
Boot 4.0.7 none 7 entries
Boot 4.1.0 none 7 entries

So every tutorial, Stack Overflow answer and internal runbook written before Boot 4 names a prefix the current appendix does not document. Check which prefix your config actually uses before assuming a setting is in force.

Worth being precise about the consequence: the default is never either way, so a stale server.error.include-stacktrace: never on Boot 4 is a line doing nothing rather than an exposed stack trace. The reverse — a deliberate always for a debugging session, left behind under the old prefix — is the case where the rename actually changes behaviour.

The full 4.x set is include-stacktrace, include-message, include-exception, include-binding-errors, path and whitelabel.enabled, all under spring.web.error..

the fix
# These are already the defaults. State them if you want them enforced
# against a future change, but there is nothing to turn on.
server:
error:
include-stacktrace: never
include-message: never
include-binding-errors: never
verify it workedRun this in: http response
Terminal window
curl -s https://example.com/path-that-throws | python3 -m json.tool

You should see timestamp, status, error, path — and no trace or message key. Trigger a real exception rather than a 404; the two take different paths.

settings on this page
spring.web.error.include-stacktraceproperty

When to include the trace attribute. Never by default, which makes Boot the one framework here that does not leak by default. on-param is client-triggered rather than a middle setting: it returns the trace whenever the caller appends the query parameter.

accepts
never | always | on-param
default
never
set in
application.properties
since
Boot 4.0 — was server.error.include-stacktrace in 3.x
Read in: Spring Boot 4.1.0 application-properties appendix
spring.web.error.include-messageproperty

When to include the message attribute. Exception messages routinely carry identifiers, SQL fragments and file paths, so always is a smaller leak than a stack trace but still a leak.

accepts
never | always | on-param
default
never
set in
application.properties
since
Boot 4.0 — was server.error.include-message in 3.x
Read in: Spring Boot 4.1.0 application-properties appendix
spring.web.error.include-exceptionproperty

Whether the response names the exception class.

accepts
true | false
default
false
set in
application.properties
since
Boot 4.0
Read in: Spring Boot 4.1.0 application-properties appendix
spring.web.error.include-binding-errorsproperty

Whether validation failures are itemised in the response.

accepts
never | always | on-param
default
never
set in
application.properties
since
Boot 4.0
Read in: Spring Boot 4.1.0 application-properties appendix
spring.web.error.whitelabel.enabledproperty

The default browser error page. On by default — it is a disclosure surface rather than a bug, and what it discloses depends on the four settings above.

accepts
true | false
default
true
set in
application.properties
since
Boot 4.0
Read in: Spring Boot 4.1.0 application-properties appendix
spring.web.error.pathproperty

Path of the error controller. This is the mapping whose absence produces the no explicit mapping for /error message.

accepts
<path>
default
/error
set in
application.properties
since
Boot 4.0
Read in: Spring Boot 4.1.0 application-properties appendix
if you see this
This application has no explicit mapping for /error, so you are seeing this as a fallback.

The Whitelabel Error Page, shown under the heading of the same name. It is a disclosure surface rather than a bug: the same page carries the exception type and, depending on the spring.web.error settings, the message and stack trace.

Read in: spring-boot module/spring-boot-webmvc/.../error/ErrorMvcAutoConfiguration.java

The finding is a project that changed these, and the usual reason is debugging:

# The lines to grep for.
spring.web.error.include-stacktrace: always
spring.web.error.include-message: always

include-stacktrace: on-param deserves a note of its own. It returns the trace when the request carries ?trace=true — which means the behaviour is client-triggered, and anyone who has read the documentation can request it. It is a debugging convenience, not a middle setting, and it does not belong in production.

include-message: always looks harmless next to a stack trace, but exception messages routinely carry the thing that failed: a file path, a SQL fragment, a host name, an upstream URL. It is a smaller leak of the same kind.

Whitelabel error pages and JSON error bodies are conservative. /actuator/heapdump is not — see what /env actually shows. If you are auditing information disclosure on a Spring Boot application, the Actuator surface is where to spend the time, not the error handler.

before you ship this

Nothing, if they are already at the defaults.

Turning them off in an environment where developers rely on them removes a debugging affordance. The replacement is structured server-side logging with a correlation id returned to the client, so support can find the trace without the client receiving it.