PoracleNG 5.2.1 changed every API error body from {status, message} to RFC 9457 application/problem+json, and moved a number of 400s to 422. Status codes are otherwise unchanged.
PoracleWeb.NET reads the old shape in the proxy layer and surfaces Poracle's own wording to the user, so on 5.2.1 every failed alarm write, human write or profile write loses its explanation and falls back to whatever the generic handler says. The 422s are worse than the 400s: a validation refusal that used to arrive as a bad request now arrives as a status we do not special-case at all.
The new shape is:
{ "type": "...", "title": "Unprocessable Entity", "status": 422, "detail": "...", "errors": [ { "message": "...", "location": "body.min_iv", "value": 200 } ] }
errors[].location is a JSON-path-ish pointer into the submitted body, which is strictly better than what we had — it can drive per-field form errors instead of one snackbar.
What to do
- Parse
problem+json in the proxies, keyed off the response content type rather than the version, so both shapes work and no capability gate is needed.
- Keep
{status, message} as the fallback for 5.1.0.
- Map
errors[].location onto the matching control in the add/edit dialogs, so a refused field is marked in place.
- Treat 422 alongside 400 everywhere we currently branch on 400.
Verify against a running instance, not the source
Per CLAUDE.md, POST a deliberately invalid rule to /api/tracking/monster/<id> on the live 5.2.1 instance and read the actual body back before writing the parser. Source and binary have disagreed before.
PoracleNG 5.2.1 changed every API error body from
{status, message}to RFC 9457application/problem+json, and moved a number of 400s to 422. Status codes are otherwise unchanged.PoracleWeb.NET reads the old shape in the proxy layer and surfaces Poracle's own wording to the user, so on 5.2.1 every failed alarm write, human write or profile write loses its explanation and falls back to whatever the generic handler says. The 422s are worse than the 400s: a validation refusal that used to arrive as a bad request now arrives as a status we do not special-case at all.
The new shape is:
{ "type": "...", "title": "Unprocessable Entity", "status": 422, "detail": "...", "errors": [ { "message": "...", "location": "body.min_iv", "value": 200 } ] }errors[].locationis a JSON-path-ish pointer into the submitted body, which is strictly better than what we had — it can drive per-field form errors instead of one snackbar.What to do
problem+jsonin the proxies, keyed off the response content type rather than the version, so both shapes work and no capability gate is needed.{status, message}as the fallback for 5.1.0.errors[].locationonto the matching control in the add/edit dialogs, so a refused field is marked in place.Verify against a running instance, not the source
Per
CLAUDE.md, POST a deliberately invalid rule to/api/tracking/monster/<id>on the live 5.2.1 instance and read the actual body back before writing the parser. Source and binary have disagreed before.