GraphQL defines the format of the reponse in case of errors[1]
GraphQL doesn't use HTTP status codes to communicate out-of-the-ordinary conditions. You can expect to always get HTTP status 200[1]
The data response is a mirror of the query you sent in with the data present[2]
How to query for data is explicitely laid out[3]
How to send in parameters is explicitely laid out[4]
[1] https://graphql.org/learn/serving-over-http/ [2] https://graphql.org/learn/ [3] https://graphql.org/learn/queries/#fields [4] https://graphql.org/learn/queries/#variables
Edit: actually you made me think a little bit more about this, if you can make your mutations idempotent, spurious retried POST requests shouldn't be a problem at all. However "delete the last record" is not an idempotent operation by definition but also one you wouldn't use in the real world - usually you delete by ID.
Edit 2: it's easy to make the server reject mutations sent via GET.
For graphql specifically, if you allow GET-ing the GraphQL endpoint (which usually isn't the case by default), it's trivial to ensure only queries go through that method.
We do have nice wrappers around the request to raise a proper named exception regardless so it doesn’t matter.