Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: web3.js RPC errors now hold the error code and data on the error object #26318

Merged
merged 1 commit into from Jun 30, 2022
Merged

feat: web3.js RPC errors now hold the error code and data on the error object #26318

merged 1 commit into from Jun 30, 2022

Conversation

steveluscher
Copy link
Contributor

@steveluscher steveluscher commented Jun 29, 2022

Problem

An RPC can fail for a variety of reasons, like you having asked for a minContextSlot that the RPC hasn't processed yet. The errors that we throw don't contain that information.

Summary of Changes

  • Create an error class to encapsulate an RPC error code, data, and a message.
  • Search for every instance of if ('error' in and replace the thrown Error with the new custom one.

@steveluscher steveluscher added enhancement New feature or request javascript Pull requests that update Javascript code labels Jun 29, 2022
customMessage: string,
): SolanaJSONRPCError {
const code = coerceSolanaJSONRPCErrorCode(error.code);
return new SolanaJSONRPCError(`${customMessage}: ${error.message}`, code);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One unfortunate side-effect of constructing the error here is that all of the stack traces will point here. The real error site will be one line below this line in the stacktrace.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we construct the error where we throw it then? Concatenating the custom and error message can happen in the SolanaJSONRPCError constructor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah; if there's no need for the extra step of coercion, then I don't need this wrapper.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh. Do you know why code is spec'd as unknown() here?

https://github.com/solana-labs/solana/blob/master/web3.js/src/connection.ts#L337

The JSON RPC spec says it must be in integer. I'm guessing that somewhere in some RPC we didn't send an integer, making this necessary?

@steveluscher steveluscher added javascript Pull requests that update Javascript code and removed javascript Pull requests that update Javascript code labels Jun 29, 2022
@codecov
Copy link

codecov bot commented Jun 29, 2022

Codecov Report

Merging #26318 (0b48f03) into master (1165a7f) will decrease coverage by 0.0%.
The diff coverage is 77.4%.

❗ Current head 0b48f03 differs from pull request most recent head 1b7fec6. Consider uploading reports for the commit 1b7fec6 to get more accurate results

@@            Coverage Diff            @@
##           master   #26318     +/-   ##
=========================================
- Coverage    81.9%    81.8%   -0.1%     
=========================================
  Files         631      671     +40     
  Lines      174252   177490   +3238     
  Branches        0      340    +340     
=========================================
+ Hits       142728   145225   +2497     
- Misses      31524    32147    +623     
- Partials        0      118    +118     

Comment on lines +31 to +32
export type SolanaJSONRPCErrorCodeEnum =
typeof SolanaJSONRPCErrorCode[keyof typeof SolanaJSONRPCErrorCode];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the benefit of adding an enum here? It feels unnecessary to me, I think we can pass through the rpc error code no matter what (without coercion) and then clients can match the code against the SolanaJSONRPCErrorCode constant they care about handling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea here was that, with an enum, you could practically create an exhaustive switch that covered every error, and the exhaustiveness of the switch could be verified with Typescript.

You're right though, that this is sort of a losing battle to push safety.

/**
* @internal
*/
function coerceSolanaJSONRPCErrorCode(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should coerce the error code because the rpc server might add new error codes and it'd be useful for clients to debug which unexpected error code they received

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair! This is one of those areas where we could enjoy the benefits of being in a monorepo, but aren't yet. If we code generated enums between Rust and JS, then we'd get updates for free (albeit still with push safety concerns).

customMessage: string,
): SolanaJSONRPCError {
const code = coerceSolanaJSONRPCErrorCode(error.code);
return new SolanaJSONRPCError(`${customMessage}: ${error.message}`, code);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we construct the error where we throw it then? Concatenating the custom and error message can happen in the SolanaJSONRPCError constructor

@steveluscher steveluscher changed the title feat: web3.js RPC errors now hold the error code on the error object feat: web3.js RPC errors now hold the error code and data on the error object Jun 30, 2022
@steveluscher steveluscher added the automerge Merge this Pull Request automatically once CI passes label Jun 30, 2022
@mergify mergify bot removed the automerge Merge this Pull Request automatically once CI passes label Jun 30, 2022
@mergify
Copy link
Contributor

mergify bot commented Jun 30, 2022

automerge label removed due to a CI failure

@steveluscher steveluscher merged commit e17ed6b into solana-labs:master Jun 30, 2022
@steveluscher steveluscher deleted the proper-error-objects-for-rpc-errors-web3js branch June 30, 2022 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request javascript Pull requests that update Javascript code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants