Open elv-gilles opened 2 months ago
Thanks for your thoughts. It's been on my TODO list to revamp how errors are populated and rendered. The current status quo isn't reflective of where we would like error reporting to get. What you proposed is fairly similar to what we would like it to eventually become.
why Hyrum-proof ?
This is precisely to provide us the ability to improve the error message in the future with less probability of breaking people who were depending on the error message being of a particular format today. While maintaining the Go stdlib, it was unfortunately common to rollback a CL because it altered the exact text of some error message, and some piece of code was depending on error string parsing to affect program logic.
We can always remove the Hyrum proofing, but not add it back. Once the error message is more stable, we can consider removing the deliberate randomization.
ok, thanks for your answer.
I'm taking as example a field
network_id
of typeuint64
and the following values entered mistakenly by a user:
123x
-123
"123:456"
The following errors are returned
with 'encoding/json':
invalid character 'x' after object key:value pair
json: cannot unmarshal number -123 into Go struct field alias.qspaces of type uint64
json: cannot unmarshal string into Go struct field alias.qspaces of type uint64
In the 2 first cases, there's at least a small chance that a user could correct himself. In the third case, the user is returned an error that has no indication of where it originated (also a user does not necessarily know about Go types).
with 'json/v2':
json: cannot unmarshal Go value of type config.AppConfig: json: cannot unmarshal Go value of type config.QSpaceConfig: json: cannot unmarshal Go value of type config.EthereumQSpaceConfig: jsontext: missing character ',' after object or array value
json: cannot unmarshal Go value of type config.AppConfig: json: cannot unmarshal Go value of type config.QSpaceConfig: json: cannot unmarshal Go value of type config.EthereumQSpaceConfig: json: cannot unmarshal JSON number into Go value of type uint64: cannot parse "-123" as unsigned integer: invalid syntax
json: cannot unmarshal Go value of type config.AppConfig: json: cannot unmarshal Go value of type config.QSpaceConfig: json: cannot unmarshal Go value of type config.EthereumQSpaceConfig: json: cannot unmarshal JSON string into Go value of type uint64
The verbosity of the error message in increased, but the user is still returned a message that does not help finding what and where the problem is.
Test code is in config_errors/config_test.go.
why not returning the offending value and location of the error ?
Ideally, the error would also indicate the name of the field where the failure occurs and would become:
"field 'network_id', invalid value '123x' at offset 133
"field 'network_id', invalid value '-123' at offset 134, cannot parse "-123" as unsigned integer
"field 'network_id', invalid value "123:456" at offset 137, cannot unmarshal JSON string into value of type uint64
With the additional change that - if the json pointer (in
SemanticErrror
) is available - replacefield 'network_id'
withpath '/x/y/network_id'
.Looking at the code :
JSONPointer
ofSemanticErrror
is never set (although the decoder has it asStackPointer()
)ByteOffset
field ofSemanticErrror
ByteOffset
ByteOffset indicates that an error occurred after this byte offset.
ByteOffset indicates that an error occurred at this byte offset.
123x
case, the root errorjsontext.SyntacticError
has its offset setadditional question: why Hyrum-proof ?
What is the reason for returning an error message (pseudo) randomly prefixed in
SemanticError
?POC / Proposal
I made some changes - limited to the 3 above cases - in this commit 6c0af11 of my
json-experiment
fork. With these changes these errors now show like this:json: cannot unmarshal Go value of type config.EthereumQSpaceConfig within JSON value at "/qspaces/0/ethereum/network_id": jsontext: missing character ',' after object or array value at byte offset 133
json: cannot unmarshal JSON number into Go value of type uint64 within JSON value at "/qspaces/0/ethereum/network_id" at byte offset 134: cannot parse "-123" as unsigned integer: invalid syntax
json: cannot unmarshal JSON string into Go value of type uint64 within JSON value at "/qspaces/0/ethereum/network_id" at byte offset 139: invalid value: "123:456"
which, in my opinion - looks more useful though still a bit long.
Further removing
Go value of type XX within JSON
from the error string would make an even better error message:json: cannot unmarshal value at "/qspaces/0/ethereum/network_id": jsontext: missing character ',' after object or array value at byte offset 133
json: cannot unmarshal value at "/qspaces/0/ethereum/network_id" at byte offset 134: cannot parse "-123" as unsigned integer: invalid syntax
json: cannot unmarshal value at "/qspaces/0/ethereum/network_id" at byte offset 139: invalid value: "123:456"
What do you think ?