Skip to content

Fix KeyError when spot token index is missing from tokens list#298

Open
RWCS-LTD wants to merge 1 commit into
hyperliquid-dex:masterfrom
RWCS-LTD:pr/spot-tokens-bounds-check
Open

Fix KeyError when spot token index is missing from tokens list#298
RWCS-LTD wants to merge 1 commit into
hyperliquid-dex:masterfrom
RWCS-LTD:pr/spot-tokens-bounds-check

Conversation

@RWCS-LTD
Copy link
Copy Markdown

Summary

Info.__init__ raises KeyError (or IndexError on pre-dict-refactor versions) and every client crashes at startup when the HL API briefly returns a universe pair whose token index is not present in spot_meta["tokens"].

Reproducer

Observed in production on 2026-05-29: HL added spot pair @367 referencing token index 479 while the tokens list held 464 entries. Every Info() caller crashed for ~54 minutes until HL repaired the response shape.

Quick repro against live API at the time of the incident:

```python
import json, urllib.request
body = json.dumps({"type": "spotMeta"}).encode()
r = urllib.request.urlopen(urllib.request.Request("https://api.hyperliquid.xyz/info", data=body, headers={"Content-Type": "application/json"}), timeout=10)
spot_meta = json.loads(r.read())
n = len(spot_meta["tokens"])
bad = [(u["name"], u["tokens"]) for u in spot_meta["universe"] if max(u["tokens"]) >= n]
print(f"Pairs with out-of-range tokens: {bad}")

Pairs with out-of-range tokens: [('@367', [479, 0])]

```

Fix

Skip universe pairs whose base or quote is not in token_by_index:

```python
if base not in token_by_index or quote not in token_by_index:
continue
```

This lets Info() initialize for all valid pairs and keeps clients alive through any future universe/tokens drift on the API side. New valid pairs come back into scope automatically as soon as their tokens land in the list.

Test

Added `tests/test_info_spot_tokens.py` with a synthetic `spot_meta` that includes one valid pair and one pair pointing at a non-existent token index. The test asserts `Info()` no longer raises and that the valid pair is still registered.

Verified the test fails on `master` without the patch (`KeyError: 5`) and passes with it.

Test plan

  • `pytest tests/test_info_spot_tokens.py` passes with the patch.
  • Same test fails on `master` without the patch.
  • Hand-tested against the live API after HL repaired the response shape — `Info()` initializes correctly and lists 463 of 464 spot tokens (the malformed pair is silently skipped, as intended, until HL adds the missing token).

When the HL API briefly returns a universe pair whose token index is not
present in spot_meta["tokens"], Info.__init__ raises KeyError and every
client crashes at startup.

Observed in production 2026-05-29: HL added spot pair @367 referencing
token index 479 while the tokens list held 464 entries. This took down
every running trader/poller using this SDK for ~54 minutes until HL
repaired the response shape.

The fix:
- Skip universe pairs whose base or quote indices are not in
  `token_by_index`.

This lets Info() initialize for all valid pairs and keeps clients alive
through any future universe/tokens drift on the API side. New valid
pairs come back into scope automatically as soon as their tokens land
in the list.

tests/test_info_spot_tokens.py reproduces the scenario with a synthetic
spot_meta and asserts Info() no longer raises while still registering
the valid pair.
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.

1 participant