Skip to main content
The things that trip up a first integration on Sui testnet. If you hit something not here, ping the team on X @altheiaxyz.

no AgentCap owned by <address>

agentRefs reads the AgentCap the agent key owns and derives the vault, policy, and cap from it. This error means the address owns no cap. Two causes:
  • Wrong key. The AGENT_PRIVKEY is not the key the agent was provisioned for. The cap is delivered to a specific address at provision time.
  • Not provisioned. The agent was never created, or the provisioning transaction did not land. Provision it in the dashboard.
The AgentCap is non-transferable, so it always lives at the address it was minted to.

A swap is denied, but I expected it to pass

Decode the abort to see why:
const ab = decodePolicyAbort(e);
console.log(ab?.reason_code);
reason_codeCheck
over_per_tx_capAmount exceeds per_tx_cap. Read it with readPolicyObject.
over_per_day_capThe rolling 24h total would exceed per_day_cap.
package_not_allowedThe pool isn’t in allowed_packages.
action_not_alloweddeepbookSwap isn’t in allowed_actions.
policy_expiredexpires_at_ms has passed.
agent_pausedThe owner paused the agent. Unpause to resume.
policy_revokedThe owner revoked the agent. Terminal — provision a new one.

A swap “failed” but decodePolicyAbort returns null

That is not a policy decision. decodePolicyAbort only decodes aborts from the policy module; it returns null for everything else. The common non-policy failure is DeepBook: a thin testnet book can fill zero, or the pool can lack liquidity at your price. Surface the raw error rather than treating it as a denial. guardedSubmit does this — it returns { ok: false } with no reason_code for a non-policy failure.

Allowed, but nothing seemed to trade

The swap is a policy decision, not a guaranteed fill. allowed (or r.ok) means the policy permitted the action and the transaction landed. On a thin testnet pool the gated DeepBook order can fill zero. Check the digest on a Sui explorer to see what settled.

Wrong network

The deployment is on testnet. Construct the client with getJsonRpcFullnodeUrl("testnet") and set your wallet to Testnet. The SUI_TESTNET ids resolve only on testnet.

Sequential actions race on object versions

keypairExecutor waits for finality after each submit so the next transaction from the same key doesn’t read a stale gas coin or object version. If you sign without it, space out transactions or wait for each digest before sending the next.

Owner operation fails: needs refs.ownerCap

revoke, pause, and killAndDrain are signed with the OwnerCap. The refs from agentRefs carry an empty ownerCap (it derives from the agent key, which has no owner authority). Build owner-side refs with the OwnerCap id and the owner key. In the dashboard, the owner wallet holds the cap and these are one click.

Open an issue

Anything not covered here, file it on GitHub or DM on X.