Attempting to redeclare a contract fails with `Internal error`
Describe the bug
When trying to declare a contract that has already been declared on testnet fails with LibraryError: -32603: Internal error.
This is the full error message:
LibraryError: -32603: Internal error
at RpcProvider.errorHandler (/Users/david/apps/issues/starknet-js-rpc/node_modules/starknet/src/provider/rpc.ts:98:13)
at RpcProvider.fetchEndpoint (/Users/david/apps/issues/starknet-js-rpc/node_modules/starknet/src/provider/rpc.ts:109:12)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Account.estimateDeclareFee (/Users/david/apps/issues/starknet-js-rpc/node_modules/starknet/src/account/default.ts:160:22)
at async Account.getSuggestedMaxFee (/Users/david/apps/issues/starknet-js-rpc/node_modules/starknet/src/account/default.ts:520:23)
at async Account.declare (/Users/david/apps/issues/starknet-js-rpc/node_modules/starknet/src/account/default.ts:332:8)
at async declareContract (/Users/david/apps/issues/starknet-js-rpc/scripts/utils.ts:71:21)
at async main (/Users/david/apps/issues/starknet-js-rpc/scripts/deploy.ts:29:9)
To Reproduce I put together a small repository to reproduce the issue. Follow the instructions in the Readme file.
Expected behavior The script should fail with a properly formatted error message so it can be handled.
Screenshots
This is the line where the library fails
Desktop (please complete the following information):
-
Browser & version [e.g. chrome, safari, webworker]: Brave Version 1.60.114 Chromium: 119.0.6045.124 (Official Build) (x86_64)
-
Node version [e.g. 16.0.1]: 20.9.0
-
Starknet.js version: 5.19.5
-
Network [devnet, testnet]: testnet
Additional context The error happens only when redeclaring. Declaring a new contract works fine.
starknet.js doesn't do anything fancy with the error response it just passes along the top level code and message. The reported issue arose because the error message that was once on the top level got moved deeper within the error response object.
It's currently not a straightforward fix that would align with earlier error handling because the error response objects are different between different nodes (Pathfinder and Juno). Making the original error response object available through LibraryError could potentially be a usable compromise.
Before trying to declare, you can test if the class already exists (provider.getClassByHash())
https://www.starknetjs.com/docs/next/API/namespaces/hash#computecontractclasshash
https://www.starknetjs.com/docs/next/API/classes/Provider#getclassbyhash
@penovicp would it make sense to return the whole error object to the user? It would help a lot with debugging
@PhilippeR26 thank you, that worked. I'll leave it up to you if you want to close the issue or not. My problem is solved but I think this might be a bigger discussion about how the library should handle errors coming from an RPC server.
@penovicp would it make sense to return the whole error object to the user? It would help a lot with debugging
In the latest pre-release the underlying error response is stringified and included in the error message, it’s just a bit clunky since it requires manual parsing. The issue will probably be kept open to be reevaluated for when the network itself is in calmer waters (or if closed, at least aggregated with other error related issues). I haven't checked, but I believe part of the issue is also that some nodes might not necessarily comply to the response specification when it comes to errors.
And to add to Phil’s recommendation, the Account class has two very convenient methods that Toni created that noticeably simplify declarations/deployments: declareIfNot encapsulates the check from Phil’s suggestion, and declareAndDeploy does what its name says and uses declareIfNot internally.
starknet.jsdoesn't do anything fancy with the error response
@penovicp I call removing essential data from the error response to the user "doing something fancy"
You could just do something like this to fix it:
errorHandler(error) {
if (error) {
- const { code, message } = error;
- throw new LibraryError(`${code}: ${message}`);
+ throw new LibraryError(JSON.stringify(error));
}
}
We can open a new issue regarding better handling errors, but closing this one as resolved.