Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.peaq.xyz/llms.txt

Use this file to discover all available pages before exploring further.

Every error raised by the SDK extends a common base. Faucet-specific codes are surfaced on the error instance (error.code) so callers can branch without string matching.

Class hierarchy

PeaqosError
├── ValidationError
├── RuntimeError
├── ValueCapExceeded
└── RateLimitExceeded
All four concrete classes extend PeaqosError directly. catch (err instanceof PeaqosError) covers every SDK error; catching RuntimeError alone will miss ValueCapExceeded and RateLimitExceeded.
import {
  PeaqosError,         // base
  ValidationError,     // bad input
  RuntimeError,        // chain or HTTP failure; carries optional `code`
  ValueCapExceeded,    // operational cap hit (extends PeaqosError)
  RateLimitExceeded,   // operational cap hit (extends PeaqosError)
} from "@peaqos/peaq-os-sdk";

Faucet error codes

All 20 codes the Gas Station can return from POST /faucet/fund, POST /2fa/setup, and POST /2fa/confirm. Each endpoint returns a subset. For example, INVALID_OWNER_ADDRESS and QR_GENERATION_FAILED only come from /2fa/setup. Codes surface as RuntimeError.code (JS) or ApiError.code (Python).
CodeDescriptionRetry
INVALID_2FAOTP rejected by the faucetYes: submit a fresh 6-digit code
2FA_NOT_CONFIGUREDOwner has not completed setup_faucet_2faNo: re-run setup
2FA_NOT_ACTIVE2FA enrolled but not confirmedNo: call confirm_faucet_2fa with a valid OTP
2FA_LOCKEDToo many invalid attempts; owner temporarily blockedAfter lockout window
CodeDescriptionRetry
DUPLICATE_REQUESTSame request_id already in flightNo: use a different request_id or wait for prior result
REQUEST_ALREADY_PROCESSEDSame request_id already resolvedNo: read the prior result
CodeDescriptionRetry
RATE_LIMITEDPer-IP or per-wallet throttle hitAfter cooldown
CAP_EXCEEDED_OWNERDaily per-owner funding cap reachedNext day
CAP_EXCEEDED_WALLETDaily per-target-wallet cap reachedNext day, or target a different wallet
CodeDescriptionRetry
INVALID_PAYLOADRequest body malformedNo: fix the payload
INVALID_OWNER_ADDRESSowner_address not a recognized formatNo
INVALID_TARGET_ADDRESStarget_wallet_address not recognizedNo
INVALID_CHAIN_IDchain_id not configured on the faucetNo
INVALID_REQUEST_IDrequest_id not a UUIDNo
CodeDescriptionRetry
TRANSFER_FAILEDOn-chain transfer reverted or stalledYes
CHAIN_RPC_ERRORFaucet’s RPC call failedYes
INTERNAL_ERRORFaucet internal failureYes
CodeDescriptionRetry
QR_NOT_FOUNDQR image expired or never createdNo: re-run setup
QR_EXPIREDQR retrieval attempted after ~2 min TTLNo: re-run setup
QR_GENERATION_FAILEDFaucet could not generate the imageYes
Full flow reference: Gas Station concept, setupFaucet2FA, fund_from_gas_station.

On-chain revert names

Revert names the SDK translates to a friendly message and surfaces as RuntimeError.code (JS) or RpcError.code (Python). The contracts define more custom errors than this table; anything not listed surfaces as code: "TX_REVERTED" (Python) or code: "<RawErrorName>" with a generic Transaction reverted: … message (JS, when viem decodes the selector).
RevertRaised byCause
AlreadyRegisteredregisterMachine / registerFor / register_machineAddress already has a machine ID
InvalidMachineAddressregisterFormachineAddress is the zero address
InvalidAddressStaking / NFT flowsCaller passed the zero address where a real address is required
AmountZeroStaking / bond flowBond amount is zero
AlreadyStakedStaking flowMachine is already bonded/staked
MachineNotBondedmintNft / mint_nftCaller’s machine is not bonded on the IdentityRegistry
AlreadyMintedmintNft / mint_nftAn NFT is already minted for the machine
NotMachineOwnermintNft / mint_nftCaller is not the owner of the machine
RecipientMustBeMachineOwnermintNft / mint_nftOperator-mint guard: recipient must be the registered machine owner
MachineNotFoundsubmitEvent / tokenIdOfmachineId has no Identity record on the IdentityRegistry
MachineDeactivatedsubmitEventThe machine has been deactivated by the IdentityRegistry
NotAuthorizedSubmittersubmitEventCaller is not authorized to submit events for this machine
InvalidEventTypesubmitEventeventType is not 0 (revenue) or 1 (activity)
InvalidTrustLevelsubmitEventtrustLevel is not 0, 1, or 2

MCR API error codes

Returned by queryMcr / query_mcr, queryMachine / query_machine, and queryOperatorMachines / query_operator_machines. Surfaced as RuntimeError.code (JS) or ApiError.code (Python).
CodeCauseRetry
NOT_FOUNDThe DID, machine, or token ID was not found by the MCR API (HTTP 404)No: check the input
BAD_RESPONSEThe MCR returned an unexpected payload shapeNo: file an issue if it persists
HTTP_ERRORThe MCR returned an unhandled non-2xx statusMaybe: surface the status code and decide
SERVER_ERRORThe MCR returned 5xxYes, with backoff
SERVICE_UNAVAILABLEThe MCR returned 503 (Service not initialised / Chain unavailable)Yes, with backoff
TIMEOUTThe HTTP request exceeded timeoutMsYes
NETWORK_ERRORTransport-level failure (DNS, TCP, TLS)Yes
ABORTEDThe caller aborted the request via AbortSignal (JS only)Caller’s choice

OWS signing error codes

Raised when transaction signing routes through an OWS vault wallet (PeaqosClient.fromWallet / from_wallet with owsSigning=true). The SDK normalises the upstream OWS error code into a typed SDK exception — only INVALID_INPUT becomes ValidationError; the other four become PeaqosError (or RuntimeError in JS) with the original OWS error preserved as .cause.
CodeCauseSurfaces as
WALLET_NOT_FOUNDVault wallet name / UUID does not existPeaqosError (Py) / RuntimeError (JS)
INVALID_PASSPHRASEWrong vault passphrasePeaqosError (Py) / RuntimeError (JS)
INVALID_INPUTMalformed transaction or sign-hash payloadValidationError(field="transaction")
POLICY_DENIEDSigning blocked by an OWS policy rulePeaqosError (Py) / RuntimeError (JS)
CHAIN_NOT_SUPPORTEDTransaction chainId is not configured in OWSPeaqosError (Py) / RuntimeError (JS)
Constants exported from both SDKs as OWS_ERROR_WALLET_NOT_FOUND, OWS_ERROR_INVALID_PASSPHRASE, OWS_ERROR_INVALID_INPUT, OWS_ERROR_POLICY_DENIED, OWS_ERROR_CHAIN_NOT_SUPPORTED. JS additionally exports the OwsSigningErrorCode union type.
import { OWS_ERROR_INVALID_PASSPHRASE, OWS_ERROR_CHAIN_NOT_SUPPORTED } from "@peaqos/peaq-os-sdk";

try {
  await client.bridgeNft({ tokenId, destination: "base" });
} catch (err) {
  if (err.cause?.code === OWS_ERROR_INVALID_PASSPHRASE) { /* prompt re-auth */ }
  if (err.cause?.code === OWS_ERROR_CHAIN_NOT_SUPPORTED) { /* OWS chain config bug */ }
  throw err;
}
from peaq_os_sdk import (
    OWS_ERROR_INVALID_PASSPHRASE,
    OWS_ERROR_CHAIN_NOT_SUPPORTED,
    PeaqosError,
)

try:
    client.bridge_nft(token_id=..., destination="base")
except PeaqosError as err:
    code = getattr(err.__cause__, "code", None)
    if code == OWS_ERROR_INVALID_PASSPHRASE:
        ...  # prompt re-auth
    if code == OWS_ERROR_CHAIN_NOT_SUPPORTED:
        ...  # OWS chain config bug
    raise

SDK transaction sentinels

Raised by the SDK’s transaction helper around any contract call. Surfaced as RuntimeError.code (JS) or RpcError.code (Python).
CodeCause
WALLET_NOT_CONFIGUREDMethod requires a signer but none was configured. (JS only; the Python PeaqosClient constructor requires a private_key and surfaces this as ValidationError.)
TX_REVERTEDThe transaction reverted on-chain. The revert reason is in the message; revert names from the table above are decoded into code when the SDK recognizes them.
RECEIPT_AWAIT_FAILEDTransaction was submitted but the SDK could not retrieve a receipt. The tx may still have landed; re-query by hash before retrying.
REGISTERED_EVENT_MISSINGReceipt has no Registered event log. Indicates a contract/SDK ABI mismatch.
REGISTERED_EVENT_MALFORMEDRegistered event log was decoded but had unexpected fields. Same root cause as above.
INVALID_FEE_RESULTquoteSend on the LayerZero ONFT adapter returned a malformed MessagingFee. Raised inside bridge_nft (Python) before submission.

Faucet / HTTP envelope sentinels

Raised by the SDK when a faucet or MCR response is reachable but unparseable. Surfaced as ApiError.code (Python). The JS SDK collapses these into the generic RuntimeError envelope path.
CodeCause
INVALID_RESPONSEFaucet returned a non-JSON body.
UNEXPECTED_RESPONSEFaucet returned JSON but the status / code / data envelope did not match the expected shape for the endpoint.
NETWORK_ERRORTransport-level failure during a faucet call (DNS, connection refused, TLS, timeout via requests.RequestException). Same sentinel as the MCR API table above.

Client-side error codes

Raised by the SDK itself (not by a chain revert). Surfaced as RuntimeError.code (JS) or ValidationError/RpcError attributes (Python).
CodeRaised byCause
MIN_BOND_INVALID_RESULTregisterMachine / registerFor (JS only)IdentityRegistry.minBond() returned a non-bigint value before submitting the bond.

Error handling patterns

import {
  PeaqosError,
  ValidationError,
  RuntimeError,
  RateLimitExceeded,
} from "@peaqos/peaq-os-sdk";

try {
  await client.fundFromGasStation(params, faucetUrl);
} catch (err) {
  if (err instanceof ValidationError) {
    // fix caller input
  } else if (err instanceof RateLimitExceeded) {
    // back off
  } else if (err instanceof RuntimeError) {
    switch (err.code) {
      case "INVALID_2FA":
        // prompt for a fresh TOTP
        break;
      case "CAP_EXCEEDED_OWNER":
      case "CAP_EXCEEDED_WALLET":
        // surface cap messaging
        break;
      default:
        throw err;
    }
  } else {
    throw err;
  }
}