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

Handle custom errors from subtensor #79

Merged

Conversation

thewhaleking
Copy link
Contributor

@thewhaleking thewhaleking commented Sep 17, 2024

Ported from opentensor/bittensor#2305

In addition to catching the typical error messages we receive, we now also catch errors embedded in SubstrateRequestExceptions by catching these exceptions explicitly and parsing the literal dicts out of the args.

E.g. AsyncSubstrateInterface.submit_extrinsic can raise a SubstrateRequestException in two ways:

A.

responses = (
    await self._make_rpc_request(
        [
            self.make_payload(
                "rpc_request",
                "author_submitAndWatchExtrinsic",
                [str(extrinsic.data)],
            )
        ],
        result_handler=result_handler,
    )
)["rpc_request"]
response = next(
    (r for r in responses if "block_hash" in r and "extrinsic_hash" in r),
    None,
)

if not response:
    raise SubstrateRequestException(responses)

which dumps a number of dict-like responses to the SubstrateRequestException's args.

or:

B.

if "result" not in response:
    raise SubstrateRequestException(response.get("error"))

which dumps the error dict to the SubstrateRequestException's args.

We handle this in both cases by parsing the SubstrateRequestException.args:

if isinstance(error_message, Exception):
    # generally gotten through SubstrateRequestException args
    new_error_message = None
    for arg in error_message.args:
        try:
            d = ast.literal_eval(arg)
            if isinstance(d, dict):
                if "error" in d:  # case A
                    new_error_message = d["error"]
                    break
                elif all(x in d for x in ["code", "message", "data"]):  # case B
                    new_error_message = d
                    break
        except ValueError:
            pass
    if new_error_message is None:  # case C
        return_val = " ".join(error_message.args)
        return f"Subtensor returned: {return_val}"
    else:
        error_message = new_error_message

This also allows us to handle the majority of raised SubstrateRequestException args which have a single string with the message included (case C).

@thewhaleking thewhaleking force-pushed the feat/thewhaleking/custom-subtensor-error-handling branch 3 times, most recently from e9492d2 to f17b796 Compare September 25, 2024 09:00
@thewhaleking thewhaleking changed the base branch from main to staging October 4, 2024 16:28
@thewhaleking thewhaleking force-pushed the feat/thewhaleking/custom-subtensor-error-handling branch from f17b796 to 51d94bf Compare October 4, 2024 16:28
@thewhaleking thewhaleking force-pushed the feat/thewhaleking/custom-subtensor-error-handling branch from 3c9b27b to 622261d Compare October 7, 2024 21:06
@thewhaleking thewhaleking merged commit ef94124 into staging Oct 7, 2024
1 check passed
@thewhaleking thewhaleking deleted the feat/thewhaleking/custom-subtensor-error-handling branch October 7, 2024 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants