feat(jsonrpc): clearer errors for malformed JSON and invalid params#3702
feat(jsonrpc): clearer errors for malformed JSON and invalid params#3702RafaelGranza wants to merge 15 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3702 +/- ##
==========================================
+ Coverage 76.67% 76.69% +0.02%
==========================================
Files 409 410 +1
Lines 37055 37181 +126
==========================================
+ Hits 28411 28517 +106
- Misses 6668 6681 +13
- Partials 1976 1983 +7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
rodrodros
left a comment
There was a problem hiding this comment.
Half done PR. Yes now more information is given to the user, but it is given in such way that is not human friendly. Let's improve upon that.
You can look into other RPCs error and get inspiration from those.
|
Here are some of the new errors: {]
^
unexpected ']', expected a string key or '}' [line 1, column 2]{"a" 1}
^
unexpected '1', expected ':' [line 1, column 6]{"a":}
^
unexpected '}', expected a value [line 1, column 6]{"a":1, }
^
unexpected trailing comma before '}' [line 1, column 9][1,2,]
^
unexpected trailing comma before ']' [line 1, column 6]{"id":@}
^
unexpected '@', expected a value [line 1, column 7]{"a": "unterminated
^
unexpected end of input [line 1, column 20]{"jsonrpc": 5, "method": "x", "id": 1}
^
field "jsonrpc" should be string, got number [line 1, column 13]^
unexpected end of input [line 1, column 1] {]
^
unexpected ']', expected a string key or '}' [line 3, column 4]...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" z}
^
unexpected 'z', expected ',' or '}' [line 1, column 230]{@yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy...
^
unexpected '@', expected a string key or '}' [line 1, column 2] |
|
Claude finished @RafaelGranza's task in 2m 46s —— View job Re-review:
|
|
Claude finished @RafaelGranza's task in 2m 5s —— View job Re-review:
|
|
Claude finished @RafaelGranza's task in 1m 7s —— View job Re-review:
|
rodrodros
left a comment
There was a problem hiding this comment.
Looks good, thank you!
Before merging, could you please swap the column which makes sense for us programmers but might not be for non-programmers. My suggestion is position or similar.
Finally, in the tests, can you please add at least one real Starknet request (multi line) with an error. The examples I saw in the unit tests are limited to 1 to 2 lines.
b479925 to
1cbb5e9
Compare
|
Claude finished @RafaelGranza's task in 3m 25s —— View job Re-review:
|
| func lineAndColumn(c *windowBuffer, markerPos int) (line, col int) { | ||
| line = c.newlinesSeen - bytes.Count(c.window[markerPos:], []byte{'\n'}) + 1 | ||
| lineStart := bytes.LastIndexByte(c.window[:markerPos], '\n') + 1 | ||
| col = utf8.RuneCount(c.window[lineStart:markerPos]) + 1 | ||
| return line, col | ||
| } |
There was a problem hiding this comment.
[nit] position is undercounted when a single logical line is longer than the window (maxWindowSize = 512).
lineStart := bytes.LastIndexByte(c.window[:markerPos], '\n') + 1 falls back to 0 when the marker's line began before the window was truncated (no newline left in the window). The column is then measured from the window start rather than the true start of the line, so the reported position drifts low.
This only bites for a single JSON line >512 bytes with the error late in that line (rare for JSON-RPC, and the existing "long line is windowed" case at ~230 bytes still fits). The caret itself stays aligned because truncateAround works off the same windowed line — only the printed position number is off. Worth a one-line comment noting the window bounds position accuracy, since the whole feature is about accurate positions.
describeError/the slices are all safe here — markerPos is bounded to [0, len(window)] by max(0, absOffset-windowStart) in prettyParseError, so no OOB. Non-blocking.
|
Claude finished @RafaelGranza's task in 4m 38s —— View job Test the
|
6232524 to
8b8ab4a
Compare
|
Claude finished @RafaelGranza's task in 3m 14s —— View job Re-review:
|
|
Claude finished @RafaelGranza's task in 3m 24s —— View job Re-review:
|
9399128 to
ad165d0
Compare
|
Claude finished @RafaelGranza's task in 2m 58s —— View job Re-review:
|
|
Claude finished @RafaelGranza's task in 3m 17s —— View job Re-review:
|
| - linters: | ||
| - lll | ||
| path: jsonrpc/server_test\.go |
There was a problem hiding this comment.
[important] The lll exemption no longer covers where the long lines live.
a903f3456 moved the parse-error table (with its very long single-line res strings) out of server_test.go and into the new jsonrpc/pretty_error_test.go. 31 lines in that new file exceed the 100-char lll limit, but this exemption still only lists jsonrpc/server_test.go — so the golangci_diff job will flag every one of them.
Broadening the path to both test files fixes it:
| - linters: | |
| - lll | |
| path: jsonrpc/server_test\.go | |
| - linters: | |
| - lll | |
| path: jsonrpc/(server|pretty_error)_test\.go |
(Or jsonrpc/.*_test\.go if you'd rather not enumerate.)
Context:
Related to Issue #3581
Before, a malformed JSON request returned only the raw decoder message.
Errors now point at what's wrong.
Also, long lines are truncated to 80 cols, so the marker stays aligned.
Errors it Covers
Examples:
Errors ate python styled.
{"id":@} ^ unexpected '@', expected a value [line 1, column 7]{"jsonrpc": 5, "method": "x", "id": 1} ^ field "jsonrpc" should be string, got number [line 1, column 13]Benchmark:
We no longer copy the whole stream, we only keep the last 512 bytes read. So the overhead stays roughly constant instead of growing with the request size.
Large requests,
main(no buffering) vs this PR:SONIC
When SONIC arrives it won't break.
Its errors already carry position, so it will just work, only not printed as nicely until we add a case for it (see the
TODOinerrorOffset).