spring-projects / spring-projects/spring-vault
VaultHealthImpl cannot deserialize sys/health when performance_standby is absent
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 306
- Forks
- 202
- PR merge metrics
- No merged PRs in 30d
Description
Summary
VaultSysTemplate.VaultHealthImpl takes performance_standby as a primitive boolean creator parameter. If the server response omits that field, deserialization fails instead of defaulting to false.
OpenBao removed performance_standby from GET /sys/health in 2.6.0, so every health check against OpenBao 2.6.0 or later throws.
Stack trace
o.s.c.v.c.VaultReactiveHealthIndicator : Health check failed
org.springframework.core.codec.DecodingException: JSON decoding error: Cannot map `null` into type `boolean`
(set `DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES` to 'false' to allow)
at org.springframework.http.codec.AbstractJacksonDecoder.processException(AbstractJacksonDecoder.java:261)
*__checkpoint ⇢ Body from GET https://openbao.example.com:8200/v1/sys/health [DefaultClientResponse]
Caused by: tools.jackson.databind.exc.MismatchedInputException: Cannot map `null` into type `boolean`
(through reference chain: org.springframework.vault.core.VaultSysTemplate$VaultHealthImpl["performance_standby"])
at tools.jackson.databind.DeserializationContext.handleNullForPrimitives(DeserializationContext.java:1467)
at tools.jackson.databind.deser.bean.PropertyValueBuffer._findMissing(PropertyValueBuffer.java:298)
The path through PropertyValueBuffer._findMissing shows this is an absent property rather than an explicit JSON null.
Why it surfaces now
Two independent changes combine.
- OpenBao 2.6.0 stopped returning
performance_standby. The field described the Vault Enterprise performance standby concept, which OpenBao is retiring in favour of all standby nodes serving reads. Their own client struct inapi/sys_health.gokeeps the field with the comment// not present in OpenBao, but left here for compatibility. - Jackson 3 enables
FAIL_ON_NULL_FOR_PRIMITIVESby default. Under Jackson 2 an absent primitive quietly becamefalse, which is why this never showed up before Spring Boot 4.
@JsonIgnoreProperties(ignoreUnknown = true) on VaultHealthImpl covers unexpected extra fields, not missing ones, so it does not help here.
Of the creator parameters, performance_standby is the only one affected. initialized, sealed, standby and server_time_utc are still returned, and replication_dr_mode is a nullable String that is already handled.
Reproduce
docker run -d -p 8200:8200 -e BAO_DEV_ROOT_TOKEN_ID=root openbao/openbao:2.6.2 server -dev -dev-listen-address=0.0.0.0:8200
curl -s http://127.0.0.1:8200/v1/sys/health
Response, with no performance_standby key:
{"initialized":true,"sealed":false,"standby":false,"replication_performance_mode":"disabled","replication_dr_mode":"disabled","server_time_utc":1788552096,"version":"2.6.2","cluster_name":"vault-cluster-8e617dcd","cluster_id":"92429cc1-b8f7-1c2b-a304-abf12923a5a2"}
The same command against openbao/openbao:2.5.4 includes "performance_standby":false and works fine.
Impact
VaultReactiveHealthIndicator and VaultHealthIndicator report DOWN with a decoding error rather than a health state. Where a Kubernetes liveness probe points at the aggregate /actuator/health, this restarts pods in a loop even though the application is running normally and has already read all of its secrets.
Suggested fix
Make performanceStandby a boxed Boolean, or otherwise let an absent performance_standby map to false. The value only feeds isPerformanceStandby(), and a server that does not report the field has no performance standby state to report.
Not a duplicate of #397 or #501
Both of those concern Vault Enterprise nodes that are performance standbys and return HTTP 473, and #397 was resolved as a synchronous RestTemplate error handling bug fixed in Spring Framework 5.2.5. This is the opposite situation: the field is absent on a healthy active node returning HTTP 200, and it reproduces on the reactive indicator, which #397 records as unaffected.
Versions
| Component | Version |
|---|---|
| Spring Boot | 4.1.0 |
| Spring Cloud | 2025.1.2 |
| spring-cloud-vault-config | 5.0.2 |
| spring-vault-core | 4.0.3 |
| jackson-databind | 3.1.4 |
| OpenBao | 2.6.0, 2.6.1, 2.6.2 |
| Java | 25 |
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with VaultSysTemplate.VaultHealthImpl and its performance_standby creator parameter. Reproduce against OpenBao 2.6.2 using the provided Docker and curl commands, then verify that the health response deserializes successfully and VaultReactiveHealthIndicator and VaultHealthIndicator no longer report a decoding error when the field is absent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100