Skip to main content

Overview

Signature errors on Hyperliquid often produce cryptic messages that don’t point to the actual cause. This guide covers the most common issues developers encounter, based on real problems reported in the Hyperliquid developer community.
For foundational signing concepts, see the authentication guide and signing overview.

”User or API Wallet does not exist” with changing addresses

This error is one of the most confusing because the wallet address in the error message changes with every request:

Why the address changes

The address isn’t random—it’s the recovered address from your signature. Hyperliquid uses ECDSA signature recovery to determine who signed the message. When your signature is malformed, the recovery produces a different (invalid) address each time.

Root causes

The action hash depends on msgpack serialization, which is order-sensitive. Different key orders produce different hashes, leading to different recovered addresses.
Hyperliquid requires lowercase addresses for signature verification:
Always lowercase addresses before signing. The SDK does this automatically, but manual implementations must handle it explicitly.
If you’re using an agent wallet that hasn’t been approved by the master account, signature recovery fails:
If your agent isn’t listed, approve it first:
Even with a valid signature, the error appears if the master account has zero balance:
Deposit USDC before attempting trades.

Debugging checklist

1

Log the exact action object

Print the action just before signing to verify structure and key order
2

Verify address formatting

Ensure all addresses are lowercase with 0x prefix
3

Check agent approval

Query user_state to confirm agent is in agentAddresses list
4

Verify account balance

Confirm the master account has collateral deposited
5

Compare with SDK output

Run the equivalent SDK method and compare the generated signature

chainId mismatch in browser wallets

When integrating with viem or wagmi, you may encounter:
Or from MetaMask:

Why this happens

Hyperliquid L1 actions require signing with chainId 1337, but your wallet is connected to Arbitrum (42161), Optimism (10), or another chain. Browser wallets enforce that the signing chain matches the connected chain.

Solutions

Best practice for frontends

For production applications, use this two-wallet pattern:
  1. Browser wallet (user’s MetaMask/WalletConnect) — signs approveAgent (chainId 0x66eee matches Arbitrum)
  2. Agent wallet (generated keypair stored locally) — signs all L1 actions (chainId 1337)

TypeScript SDK options

Hyperliquid has two community TypeScript SDKs:

@nktkas/hyperliquid examples

Install:

reserveRequestWeight for HIP-3 builders

If you’re building a HIP-3 DEX and need to push oracle prices, you’ll encounter reserveRequestWeight—an action that uses a unique hybrid signing pattern.

The edge case

Most actions follow clear rules:
  • L1 actions → phantom agent schema, signed by agent wallet
  • User-signed actions → direct EIP-712, signed by user wallet
reserveRequestWeight breaks this pattern: it uses the agent-style schema but must be signed by the user wallet.
This hybrid exists because oracle updates need the authority of the main account but use the same submission path as L1 actions.

Implementation

Error reference

Summary

Most Hyperliquid signature errors fall into three categories:
  1. Serialization issues — Key ordering, address casing, missing fields
  2. Chain ID confusion — Using wrong chainId for L1 vs user-signed actions
  3. Wallet configuration — Agent not approved, no funds, wrong wallet type
When debugging, always start by comparing your implementation against the SDK’s output—it handles all the edge cases correctly.
Last modified on June 24, 2026