Skip to main content

How to debug anything on Cowboy

  1. Read the receipt. Failed transactions carry an E-code, gas usage, and often a Python traceback: cowboy transaction status --hash <tx> or GET /transaction/{hash}/receipt.
  2. Map the E-code. Execution errors carry stable codes — see the error reference for the taxonomy (E1000s pre-checks through E1900s fallback).
  3. Check node health: cowboy status (height, mempool, basefee) and GET /health/detailed.
The sections below cover the failures people actually hit, in journey order.

Devnet won’t start / can’t connect

SymptomCauseFix
peers file does not exist when starting the validatorDevnet config never generated./scripts/run_build.sh (generates test/ config + genesis)
Validator exits immediately, or connection refused on :4000Validator not running, or RPC port takenpgrep validator / docker ps; check the port (nc -zv localhost 4000); inspect test/validator.log
Stale state weirdness after restarts (old actors, odd nonces)Leftover test/ data from a previous run./scripts/restart_validator.sh (clears test data), or rm -rf test/ && ./scripts/run_build.sh
429 Too Many Requests while scriptingGlobal rate limit (default 100 req/s)Back off, or raise RPC_GLOBAL_RATE_LIMIT_PER_SEC on your own devnet

Wallet and CLI

SymptomCauseFix
Failed to load private key / key not foundNo key at any lookup locationKey resolution is --private-keyCOWBOY_PRIVATE_KEY → the active environment’s key_file.cowboy/key. Run cowboy init local to scaffold, or cowboy wallet create
Insufficient balance (E1003/E1004)Account unfunded, or balance can’t cover gas_limit × basefeeDevnet: faucet (cowboy init funds you automatically, or POST /faucet). Otherwise cowboy transfer from a funded account; check with cowboy wallet balance
Nonce mismatch (E1002)Tx nonce ≠ account nonce (parallel submissions, stale cache)cowboy account nonce --address <addr>, resubmit; serialize submissions per account
CLI hits the wrong networkEnv/flag overriding project configRemember the precedence: --rpc-url flag beats COWBOY_RPC_URL beats .cowboy/config.json

Deploying actors

SymptomCauseFix
Invalid salt hex--salt must be a hex string (≤ 32 bytes)Use e.g. --salt 0x01, not an arbitrary name
Non-deterministic code rejected (E1101)Banned import (os, pickle, datetime, ctypes, …) or banned pattern (asyncio.gather, giant integer literal)See the PVM rules; use runtime APIs for time/randomness and runner.* continuations for I/O
Out of Cycles / Cells at deploy (E1005/E1006)init work exceeds default limitsRaise --cycles-limit / --cells-limit on the deploy; trim init
Basefee too low (E1008)Network basefee moved above your max feeCheck cowboy status for current basefees and raise --max-fee-per-cycle / --max-fee-per-cell

Executing handlers

SymptomCauseFix
Handler not foundHandler name typo, or no module-level entrypointHandlers are dispatched by top-level function name — confirm the module-level wrapper exists; check cowboy actor get
Permission denied (E1211)SDK handlers are deny-by-defaultMark the handler @public (or @callable_by(...)), or call from an authorized address
Out of gas mid-execution (E1201 / E1005 / E1006)Cycles or Cells exhausted; storage reads settle after execution, so read-heavy handlers can fail lateRaise limits on the execute call; batch reads; trim returned data (1 Cell/byte)
Invalid input (E1202)Address not 20 bytes, malformed CBOR payloadEncode payloads with cowboy_sdk.codec; pass addresses as 20-byte hex
Generic PVM error with traceback (E1210)Unhandled Python exception in the handlerRead the traceback in the receipt; reproduce off-chain with the SimulatedChain test harness
Token transfer silently blocked, hook at fault (E1408 / E1411 / E1412)can_transfer hook rejected (fail-closed — anything but "true"/"1"/JSON true rejects), or blew its 50k Cycle cap (E1411) / 50k Cell cap (E1412)Inspect the hook actor’s logic; keep hooks tiny

Runner jobs

SymptomCauseFix
Runner not found (E1602)Daemon’s address never registeredFund the runner address, then cowboy runner register --stake 50000
Insufficient stake at registration (E1603)Stake below the minimum, or below 1.5× the runner’s declared maximum job valueRegister with a larger --stake, or declare a lower max job value
Job stuck pendingNo registered runner matches the job’s requirements or covers its price at 1.5× stake (under-staked runners are silently filtered from candidacy — no error is raised)curl /runners/active; start/register a matching, sufficiently staked runner; check its heartbeats
LLM jobs fail on the runnerMissing executor credentialsSet OPENAI_API_KEY / ANTHROPIC_API_KEY in the runner daemon’s environment
No consensus / threshold not met (E1608/E1609)Runners disagreed, or too few submitted before the deadlineAdd runners; pick a verification mode suited to non-deterministic output (see verification modes)
Callback never firesJob still unverified, or callback handler name doesn’t matchGET /job/{id}/status; confirm the actor exposes the resume/callback handler at module level

Reading the E-code taxonomy

RangeDomain
E1000–E1099Transaction pre-checks (signature, nonce, balance, basefee)
E1100–E1199Static code validation
E1200–E1299PVM runtime / host API
E1300–E1399Entitlements / manifests
E1400–E1499CIP-20 tokens & transfer hooks
E1500–E1599Timers, deferred, commit-reveal
E1600–E1699Runners, jobs, verification consensus
E1700–E1899Secrets (CBSS) & Watchtower streams (defined in the node; per-code pages not yet published)
E1900–E1999Unclassified fallback — report it with the tx hash
Most codes have a dedicated page with causes and remedies: error reference.

Still stuck?

  • The Quickstart troubleshooting accordions cover first-run issues (PATH, Docker, config pointing at the wrong RPC).
  • The FAQ answers conceptual “why does it work this way” questions.
  • For protocol-level behavior, the CIP specs are authoritative.