From 6db245aacd630c4b568d6cb97459f7c7696a5136 Mon Sep 17 00:00:00 2001 From: Steve Chavez Date: Wed, 20 Nov 2024 12:15:46 -0500 Subject: [PATCH] fix: clarify PGRST116 error message (#3795) Currently it's redundant and not easy to read. ``` {"message":"JSON object requested, multiple (or no) rows returned", "details":"The result contains 2 rows"} ``` Now: ``` {"message":"Cannot coerce the result to a single JSON object", "details":"The result contains an array of 0 objects"} `` Also correct docs which had a wrong error code. --- CHANGELOG.md | 1 + .../api/resource_representation.rst | 10 +++--- src/PostgREST/Error.hs | 2 +- test/spec/Feature/Query/NullsStripSpec.hs | 2 +- test/spec/Feature/Query/SingularSpec.hs | 32 +++++++++---------- 5 files changed, 23 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd2b1382d..4141eb975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). + Fixed `"column reference is ambiguous"` error when selecting `?select=...table(col,count())` + Fixed `"column . does not exist"` error when selecting `?select=...table(aias:count())` - #3727, Clarify "listening" logs - @steve-chavez + - #3795, Clarify `Accept: vnd.pgrst.object` error message - @steve-chavez - #3779, Always log the schema cache load time - @steve-chavez ### Changed diff --git a/docs/references/api/resource_representation.rst b/docs/references/api/resource_representation.rst index e3586e040..b3af71b13 100644 --- a/docs/references/api/resource_representation.rst +++ b/docs/references/api/resource_representation.rst @@ -74,17 +74,15 @@ This returns { "id": 1 } -with a :code:`Content-Type: application/vnd.pgrst.object+json`. - When a singular response is requested but no entries are found, the server responds with an error message and 406 Not Acceptable status code rather than the usual empty array and 200 status: .. code-block:: json { - "message": "JSON object requested, multiple (or no) rows returned", - "details": "Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row", - "hint": null, - "code": "PGRST505" + "code": "PGRST116", + "message": "Cannot coerce the result to a single JSON object", + "details": "The result contains 0 rows", + "hint": null } .. note:: diff --git a/src/PostgREST/Error.hs b/src/PostgREST/Error.hs index 9cd0f80f9..8f386a800 100644 --- a/src/PostgREST/Error.hs +++ b/src/PostgREST/Error.hs @@ -163,7 +163,7 @@ instance JSON.ToJSON ApiRequestError where toJSON (SingularityError n) = toJsonPgrstError ApiRequestErrorCode16 - "JSON object requested, multiple (or no) rows returned" + "Cannot coerce the result to a single JSON object" (Just $ JSON.String $ T.unwords ["The result contains", show n, "rows"]) Nothing diff --git a/test/spec/Feature/Query/NullsStripSpec.hs b/test/spec/Feature/Query/NullsStripSpec.hs index ef5c0c578..af562d2a2 100644 --- a/test/spec/Feature/Query/NullsStripSpec.hs +++ b/test/spec/Feature/Query/NullsStripSpec.hs @@ -70,7 +70,7 @@ spec = [singularStrip] "" `shouldRespondWith` - [json|{"details":"The result contains 6 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 6 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [matchContentTypeJson] } diff --git a/test/spec/Feature/Query/SingularSpec.hs b/test/spec/Feature/Query/SingularSpec.hs index 1f856166e..86c58a33d 100644 --- a/test/spec/Feature/Query/SingularSpec.hs +++ b/test/spec/Feature/Query/SingularSpec.hs @@ -70,7 +70,7 @@ spec = [("Prefer", "tx=commit"), singular] [json| { address: "zzz" } |] `shouldRespondWith` - [json|{"details":"The result contains 4 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 4 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [ matchContentTypeJson ] } @@ -85,7 +85,7 @@ spec = [("Prefer", "tx=commit"), ("Prefer", "return=representation"), singular] [json| { address: "zzz" } |] `shouldRespondWith` - [json|{"details":"The result contains 4 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 4 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [ matchContentTypeJson ] } @@ -99,7 +99,7 @@ spec = request methodPatch "/items?id=gt.0&id=lt.0" [singular] [json|{"id":1}|] `shouldRespondWith` - [json|{"details":"The result contains 0 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 0 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [matchContentTypeJson] } @@ -108,7 +108,7 @@ spec = request methodPatch "/items?id=gt.0&id=lt.0" [("Prefer", "return=representation"), singular] [json|{"id":1}|] `shouldRespondWith` - [json|{"details":"The result contains 0 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 0 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [matchContentTypeJson] } @@ -141,7 +141,7 @@ spec = [("Prefer", "tx=commit"), singular] [json| [ { id: 200, address: "xxx" }, { id: 201, address: "yyy" } ] |] `shouldRespondWith` - [json|{"details":"The result contains 2 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 2 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [ matchContentTypeJson ] } @@ -156,7 +156,7 @@ spec = [("Prefer", "tx=commit"), ("Prefer", "return=representation"), singular] [json| [ { id: 202, address: "xxx" }, { id: 203, address: "yyy" } ] |] `shouldRespondWith` - [json|{"details":"The result contains 2 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 2 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [ matchContentTypeJson ] } @@ -171,7 +171,7 @@ spec = [("Prefer", "tx=commit"), ("Prefer", "return=minimal"), singular] [json| [ { id: 204, address: "xxx" }, { id: 205, address: "yyy" } ] |] `shouldRespondWith` - [json|{"details":"The result contains 2 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 2 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [ matchContentTypeJson ] } @@ -186,7 +186,7 @@ spec = [singular] [json| [ ] |] `shouldRespondWith` - [json|{"details":"The result contains 0 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 0 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [matchContentTypeJson] } @@ -196,7 +196,7 @@ spec = [("Prefer", "return=representation"), singular] [json| [ ] |] `shouldRespondWith` - [json|{"details":"The result contains 0 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 0 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [matchContentTypeJson] } @@ -219,7 +219,7 @@ spec = [("Prefer", "tx=commit"), singular] "" `shouldRespondWith` - [json|{"details":"The result contains 5 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 5 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [ matchContentTypeJson ] } @@ -236,7 +236,7 @@ spec = request methodDelete "/items?id=gt.5&id=lt.11" [("Prefer", "tx=commit"), ("Prefer", "return=representation"), singular] "" `shouldRespondWith` - [json|{"details":"The result contains 5 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 5 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [ matchContentTypeJson ] } @@ -252,7 +252,7 @@ spec = request methodDelete "/items?id=lt.0" [singular] "" `shouldRespondWith` - [json|{"details":"The result contains 0 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 0 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [matchContentTypeJson] } @@ -261,7 +261,7 @@ spec = request methodDelete "/items?id=lt.0" [("Prefer", "return=representation"), singular] "" `shouldRespondWith` - [json|{"details":"The result contains 0 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 0 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [matchContentTypeJson] } @@ -271,7 +271,7 @@ spec = request methodPost "/rpc/getproject" [singular] [json|{ "id": 9999999}|] `shouldRespondWith` - [json|{"details":"The result contains 0 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 0 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [matchContentTypeJson] } @@ -294,7 +294,7 @@ spec = request methodPost "/rpc/getallprojects" [singular] "{}" `shouldRespondWith` - [json|{"details":"The result contains 5 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 5 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [matchContentTypeJson] } @@ -309,7 +309,7 @@ spec = [("Prefer", "tx=commit"), singular] [json| {"id_l": 1, "id_h": 2, "name": "changed"} |] `shouldRespondWith` - [json|{"details":"The result contains 2 rows","message":"JSON object requested, multiple (or no) rows returned","code":"PGRST116","hint":null}|] + [json|{"details":"The result contains 2 rows","message":"Cannot coerce the result to a single JSON object","code":"PGRST116","hint":null}|] { matchStatus = 406 , matchHeaders = [ matchContentTypeJson ] }