Troubleshooting
Common issues and solutions for Self Agent ID integration
userDefinedData encoding fails
userDefinedData encoding failsThis is the #1 integration mistake.
The Self SDK passes userDefinedData as a UTF-8 string, not raw bytes. Each position uses the ASCII character — '0' (0x30), not 0x00.
// WRONG — raw byte value
bytes32 data = bytes32(uint256(0));
// CORRECT — ASCII character
bytes32 data = bytes32(bytes1(uint8(uint8(bytes1("0")))));Use bytes32(bytes1(uint8(x))) for byte positioning in bytes32.
If your contract receives garbled userDefinedData, this is almost certainly the cause.
"Agent not verified" when querying
Possible causes:
Wrong chain ID — Are you querying the right network? Mainnet is
42220, testnet is11142220.Wrong registry address — Each network has its own registry. See Smart Contracts for addresses.
Agent not yet registered — Registration requires the Self app callback to complete. Poll with
self_check_registrationor the REST API status endpoint.Agent was deregistered — The soulbound NFT was burned. Re-registration is needed.
Proof expired — The agent's human proof has passed its validity window. Check
isProofFresh(agentId)— if it returnsfalse, the agent must re-authenticate by scanning their passport again.
Agent proof expired
If isProofFresh() returns false but hasHumanProof() returns true:
The proof validity window has elapsed (default: 1 year or document expiry, whichever is sooner)
The soulbound NFT is NOT burned — it remains as a historical record
The agent must re-authenticate via the Self app to restore fresh status
SDK verifiers automatically reject expired proofs with a descriptive error
Registration callback never arrives
Check these:
SELF_ENDPOINTtype mismatch — Usecelofor mainnet,staging_celofor testnet. If set wrong, the Self app sends the callback to the wrong network..env.localkey must be lowercase —NEXT_PUBLIC_SELF_ENDPOINT(notNEXT_PUBLIC_Self_Endpoint). Environment variable names are case-sensitive.Callback URL not reachable — If running locally, ensure the callback port is accessible. The CLI binds to
127.0.0.1by default.Session expired — Sessions have a 30-minute TTL. Start a new registration if expired.
Signature verification fails
Common causes:
Timestamp drift — The verifier rejects signatures older than 5 minutes (default). Ensure client and server clocks are in sync.
Body encoding — The signature covers
keccak256(timestamp + METHOD + path + bodyHash). If the body is modified in transit (e.g., by a proxy re-serializing JSON), verification fails.Path vs full URL — The SDK signs the URL path (e.g.,
/api/data), not the full URL. Ensure your verifier extracts the path correctly.Wrong private key — The signing key must match the registered agent address.
Wrong chain ID
Celo Sepolia chain ID is 11142220, not 44787 (deprecated Alfajores). This is a common mistake when migrating from older Celo testnet configurations.
Celo Mainnet
42220
https://forno.celo.org
Celo Sepolia
11142220
https://forno.celo-sepolia.celo-testnet.org
Foundry build fails
If you see errors about PUSH0 or unsupported opcodes:
Add to foundry.toml:
Provider verification untrusted
If agents pass isVerifiedAgent() but you don't trust the proof source:
Without requireSelfProvider(), any approved provider's proofs are accepted. Self Protocol's provider is the only one currently deployed, but this guard protects against future third-party providers.
WebAuthn / passkey errors
Firefox blocks WebAuthn on http://localhost. Use one of:
Chrome on
http://localhost(Chrome allows it)HTTPS with a local cert (e.g.,
mkcert)Deployed URL with HTTPS
This only affects smart wallet mode (passkey-based registration).
Smart wallet not gasless on testnet
Smart wallet mode is counterfactual only on testnet — the smart account address is computed but not deployed, so gasless transactions aren't available.
On mainnet, the Pimlico paymaster sponsors gas for registration transactions, enabling full gasless UX.
Blockscout / Celoscan verification issues
Blockscout does not require an API key for contract verification.
Celoscan — use the Sourcify verifier (not the etherscan verifier). The Celoscan API endpoint is flaky; Sourcify is more reliable.
"InvalidIdentityCommitmentRoot" error
You're using the wrong network. Real passports only work on mainnet (Celo, chain ID 42220). Mock documents only work on testnet (Celo Sepolia, chain ID 11142220). Make sure your registration network matches your document type.
A2A endpoint unreachable
If other agents cannot reach your A2A endpoint:
Endpoint not registered — The
agentURImetadata must include the A2A endpoint URL. Check thatsetAgentURI()was called after registration.Firewall / NAT — Your A2A server must be publicly reachable. If running locally, use a tunnel (e.g.,
ngrok) and register the tunnel URL as your endpoint.TLS required — A2A endpoints must be served over HTTPS. Plain HTTP connections are rejected by most agent runtimes.
CORS misconfigured — If the calling agent is browser-based, your A2A server must return appropriate
Access-Control-Allow-Originheaders.Wrong path — The default A2A path is
/.well-known/agent.jsonfor the agent card. Ensure your server serves the agent card at that path and theurlfield inside it points to the correct task endpoint.
MCP "no identity" error
If MCP tools that require identity (sign, fetch, get identity) fail:
SELF_AGENT_PRIVATE_KEYis not set in your MCP configQuery tools (
self_lookup_agent,self_verify_agent,self_list_agents_for_human) work without a keySet the key in your MCP config
envblock to enable full mode
Last updated