Summary
POST /boundary-service/boundary/_search (the boundary entity search) returns HTTP 400 for any boundary whose additionaldetails column is NULL:
{"ResponseInfo":null,"Errors":[{"id":"IllegalArgumentException","code":"An unhandled exception occurred on the server","message":"argument \"content\" is null"}]}
The boundary relationship search (/boundary-relationships/_search) is unaffected — it doesn't map the entity's jsonb columns.
Root cause
core-services/boundary-service/src/main/java/digit/repository/rowmapper/BoundaryEntityRowMapper.java calls ObjectMapper.readTree(...) directly on the column values:
.geometry(mapper.readTree(resultSet.getString("geometry")))
.additionalDetails(mapper.readTree(resultSet.getString("additionaldetails")))
When additionaldetails (or geometry) is SQL NULL, resultSet.getString(...) returns null, and Jackson's readTree(String) throws IllegalArgumentException: argument "content" is null (from _assertNotNull("content", content)). It is not caught by the surrounding catch (JsonProcessingException e), so it propagates as an unhandled 500/400.
Both jsonb columns are nullable in the schema, and additionaldetails is legitimately null for boundaries created without it.
Impact
Beyond the endpoint itself, egov-hrms employee _create calls /boundary/_search to validate the employee's jurisdiction, so employee onboarding fails for every row when the tenant's boundaries have null additionaldetails — with the same opaque argument "content" is null message surfaced in HRMS, which makes it hard to trace back to boundary-service.
Reproduction
- Insert a boundary with
additionaldetails = NULL (the default when created without it).
POST /boundary-service/boundary/_search?tenantId=<t>&codes=<code> → 400 argument "content" is null.
- Set
additionaldetails = '{}'::jsonb on that row → the same call returns 200.
Suggested fix
Null-guard both jsonb columns before readTree:
String geometryJson = resultSet.getString("geometry");
String additionalDetailsJson = resultSet.getString("additionaldetails");
boundary = Boundary.builder()
.id(resultSet.getString("id"))
.code(resultSet.getString("code"))
.auditDetails(auditDetails)
.geometry(geometryJson != null ? mapper.readTree(geometryJson) : null)
.additionalDetails(additionalDetailsJson != null ? mapper.readTree(additionalDetailsJson) : null)
.tenantId(resultSet.getString("tenantid"))
.build();
Environment
- Image:
egovio/boundary-service:maven-jdk21-9f83afb
- Observed on a DIGIT/PGR deployment; confirmed both the failure and that
additionaldetails='{}' resolves it, and that a full HRMS employee _create then succeeds end to end.
Summary
POST /boundary-service/boundary/_search(the boundary entity search) returns HTTP 400 for any boundary whoseadditionaldetailscolumn isNULL:{"ResponseInfo":null,"Errors":[{"id":"IllegalArgumentException","code":"An unhandled exception occurred on the server","message":"argument \"content\" is null"}]}The boundary relationship search (
/boundary-relationships/_search) is unaffected — it doesn't map the entity's jsonb columns.Root cause
core-services/boundary-service/src/main/java/digit/repository/rowmapper/BoundaryEntityRowMapper.javacallsObjectMapper.readTree(...)directly on the column values:When
additionaldetails(orgeometry) is SQLNULL,resultSet.getString(...)returnsnull, and Jackson'sreadTree(String)throwsIllegalArgumentException: argument "content" is null(from_assertNotNull("content", content)). It is not caught by the surroundingcatch (JsonProcessingException e), so it propagates as an unhandled 500/400.Both jsonb columns are nullable in the schema, and
additionaldetailsis legitimately null for boundaries created without it.Impact
Beyond the endpoint itself,
egov-hrmsemployee_createcalls/boundary/_searchto validate the employee's jurisdiction, so employee onboarding fails for every row when the tenant's boundaries have nulladditionaldetails— with the same opaqueargument "content" is nullmessage surfaced in HRMS, which makes it hard to trace back to boundary-service.Reproduction
additionaldetails = NULL(the default when created without it).POST /boundary-service/boundary/_search?tenantId=<t>&codes=<code>→ 400argument "content" is null.additionaldetails = '{}'::jsonbon that row → the same call returns 200.Suggested fix
Null-guard both jsonb columns before
readTree:Environment
egovio/boundary-service:maven-jdk21-9f83afbadditionaldetails='{}'resolves it, and that a full HRMS employee_createthen succeeds end to end.