Context
In `services/catalogue-service/catalogue-db-queries.go` the range-typed property logic uses:
```cypher
apoc.convert.fromJsonMap(pv.value)
```
Two locations:
`apoc.convert.fromJsonMap` on a malformed string throws a Cypher-level exception — the whole query 500s, not just the one row.
Why this matters now
PR #416 made range-typed properties sortable, which means a single bad-data row in any item that has a range custom property → entire list endpoint dies whenever someone sorts by that column.
Mitigation options
- Defensive parse: switch to a lenient JSON helper or wrap in `apoc.do.when` with a fallback to null.
- Type-coerce-and-skip: `CASE WHEN pv.value STARTS WITH '{' THEN apoc.convert.fromJsonMap(pv.value).min ELSE null END` — handles the most common bad-data case (empty string).
- Backfill: data audit + normalize all range values to valid JSON.
Option 2 is the cheapest defensive fix.
Acceptance
- Inject a row with `pv.value = 'bogus'` for a range property; the sort + filter queries still return 200.
- Item appears at the head/tail (null sort) instead of crashing the response.
Context
In `services/catalogue-service/catalogue-db-queries.go` the range-typed property logic uses:
```cypher
apoc.convert.fromJsonMap(pv.value)
```
Two locations:
`apoc.convert.fromJsonMap` on a malformed string throws a Cypher-level exception — the whole query 500s, not just the one row.
Why this matters now
PR #416 made range-typed properties sortable, which means a single bad-data row in any item that has a range custom property → entire list endpoint dies whenever someone sorts by that column.
Mitigation options
Option 2 is the cheapest defensive fix.
Acceptance