Error Codes Reference
This document provides a complete runbook-style reference for all error, warning, and info codes used by 8004scan's parsing system. Each code has a unique anchor for direct linking (e.g., #EA001).
Overview
Code Format
All error codes follow the format <Severity><Object><Number>:
| Component | Values | Description |
|---|---|---|
| Severity | E W I | Error (critical), Warning (non-critical), Info (recommendation) |
| Object | A F | Agent metadata, Feedback data |
| Number | 001-999 | Sequence number within category |
Severity Levels
| Level | RFC 2119 | Parse Result | User Action |
|---|---|---|---|
| Error (E) | MUST fix | Parse fails, agent not indexed | Required to index agent |
| Warning (W) | SHOULD fix | Parse succeeds with issues | Recommended to fix |
| Info (I) | MAY fix | Parse succeeds | Optional improvement |
Linking to Error Codes
Each error code can be directly linked:
https://best-practices.8004scan.io/docs/implementation/error-codes.html#EA001
https://best-practices.8004scan.io/docs/implementation/error-codes.html#WA070Field Name Migration Note
Important: As of January 2026, the official EIP-8004 specification uses
servicesinstead ofendpointsfor the top-level array field in agent metadata. However:
- Error codes referencing
endpoints: Still valid - parsers must support both field names for backward compatibility- Example code below: Updated to use
services(current best practice)- Legacy field support: The
endpointsfield name will continue to work, triggering warning code WA031See Agent Metadata Standard - Field Migration for complete details.
Agent Errors (EA001-EA099)
Critical issues that prevent agent metadata parsing. These MUST be fixed for the agent to be indexed.
EA001
Empty or invalid URI
| Property | Value |
|---|---|
| Code | EA001 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| ERC-8004 Reference | tokenURI() function (ERC-721 interface) |
Description
The agent's metadata URI is empty, null, or not a valid string. Without a valid URI, there is no metadata to parse.
Common Causes
- Agent registered without metadata: The
register()transaction was called but noagentURIwas set - Subgraph sync issue: The subgraph returned null for
tokenURI - Contract misconfiguration: Custom registry doesn't implement ERC-721 metadata interface correctly
Diagnostic Steps
Check the on-chain
tokenURI(tokenId)return value:solidity// Etherscan > Read Contract > tokenURI tokenURI(123) // Should return a valid URI stringVerify the agent was registered:
solidityownerOf(tokenId) // Should return a valid addressCheck subgraph indexing status at the Graph Explorer
Resolution
Option 1: Set the agentURI on-chain (if contract supports it):
registry.setAgentURI(tokenId, "ipfs://Qm...");Option 2: Re-register the agent with a valid URI
Option 3: If using a custom registry, ensure it implements:
function tokenURI(uint256 tokenId) external view returns (string memory);Example API Response
{
"parse_status": {
"status": "error",
"errors": [
{
"code": "EA001",
"field": "agentURI",
"message": "Empty or invalid URI: null"
}
]
}
}EA002
Invalid JSON syntax
| Property | Value |
|---|---|
| Code | EA002 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| ERC-8004 Reference | Agent metadata MUST be valid JSON |
Description
The metadata content fetched from the URI is not valid JSON. The parser cannot extract any agent information.
Common Causes
- Malformed JSON: Syntax errors like missing quotes, trailing commas, or unescaped characters
- HTML error page: Server returned an error page instead of JSON (e.g., 404, 500)
- Encoding corruption: Character encoding issues corrupted the JSON structure
- Truncated response: Network issues caused incomplete data transfer
Diagnostic Steps
Fetch the URI content manually:
bashcurl -s "https://your-agent-uri.com/metadata.json" | jq .Validate JSON syntax:
bashcurl -s "https://..." | python -m json.toolCheck Content-Type header:
bashcurl -I "https://..." | grep -i content-type # Expected: application/json
Resolution
- Fix JSON syntax: Use a JSON linter (jsonlint.com, VSCode)
- Check server configuration: Ensure server returns
Content-Type: application/json - Escape special characters: In data URIs, ensure proper escaping
- Re-upload to IPFS: If content was corrupted, re-upload the correct JSON
Valid JSON Example
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "My Agent",
"description": "Agent description"
}Common JSON Errors
// ❌ Trailing comma (invalid)
{ "name": "Agent", }
// ❌ Single quotes (invalid)
{ 'name': 'Agent' }
// ❌ Unquoted keys (invalid)
{ name: "Agent" }
// ❌ Unescaped newlines in strings (invalid)
{ "description": "Line 1
Line 2" }EA003
Invalid base64 encoding
| Property | Value |
|---|---|
| Code | EA003 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| Reference | RFC 4648 (Base64 Data Encodings) |
Description
The data URI claims to be base64-encoded (data:application/json;base64,...) but contains invalid base64 characters or incorrect padding.
Common Causes
- Incorrect padding: Base64 strings must be padded with
=to make length a multiple of 4 - Invalid characters: Non-base64 characters (anything outside A-Z, a-z, 0-9, +, /)
- Whitespace: Line breaks or spaces within the encoded string
- URL-safe encoding mismatch: Using URL-safe base64 (
-_) with standard decoder
Diagnostic Steps
Extract and test the base64 portion:
bash# Extract base64 content (after the comma) echo "eyJ0eXBlIjoi..." | base64 -dCheck for invalid characters:
bashecho "eyJ0eXBlIjoi..." | grep -P '[^A-Za-z0-9+/=]'Verify padding:
pythonimport base64 data = "eyJ0eXBlIjoi..." # Should have length divisible by 4 (with padding) print(len(data) % 4) # Should be 0
Resolution
Re-encode correctly:
pythonimport base64 import json metadata = {"type": "...", "name": "..."} encoded = base64.b64encode(json.dumps(metadata).encode()).decode() data_uri = f"data:application/json;base64,{encoded}"Remove whitespace: Ensure no line breaks in the encoded string
Fix padding: Add
=characters if needed:python# Fix padding data = data + '=' * (4 - len(data) % 4) if len(data) % 4 else data
Example
# ✅ Valid base64 data URI
data:application/json;base64,eyJ0eXBlIjoiaHR0cHM6Ly9laXBzLmV0aGVyZXVtLm9yZy9FSVBzL2VpcC04MDA0I3JlZ2lzdHJhdGlvbi12MSIsIm5hbWUiOiJUZXN0In0=
# ❌ Invalid (contains spaces)
data:application/json;base64,eyJ0eXBl Ijoi...
# ❌ Invalid (missing padding)
data:application/json;base64,eyJ0eXBlIjoiaHR0cHM6Ly9laXBzEA004
Decompression security error (possible zip bomb)
| Property | Value |
|---|---|
| Code | EA004 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| Security | Zip bomb protection |
Description
The compressed data would decompress to more than 100KB, which is rejected as a security measure against zip bomb attacks.
Why This Limit Exists
A zip bomb is a malicious compressed file designed to crash or overwhelm systems when decompressed. A small compressed file (few KB) can expand to gigabytes or terabytes of data.
Common Causes
- Actual attack: Malicious agent attempting to DoS the indexer
- Excessive metadata: Agent metadata far exceeds reasonable size
- Embedded large data: Binary data (images) embedded in JSON
Resolution
Reduce metadata size: Agent metadata should typically be 1-10KB
Use external references: Store large data (images, files) externally:
json{ "image": "ipfs://Qm...", // ✅ External reference "image": "data:image/png;base64,..." // ❌ Embedded (large) }Use IPFS/HTTP for large metadata: Instead of data URI compression
Size Guidelines
| Content | Recommended Max Size |
|---|---|
| Total metadata JSON | 50KB |
| Compressed data URI | 20KB |
| Decompressed limit | 100KB (hard limit) |
EA005
Decompression failed
| Property | Value |
|---|---|
| Code | EA005 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| Reference | Data URI Compression Extension |
Description
The compressed data could not be decompressed with the specified algorithm. The enc= parameter doesn't match the actual compression format.
Supported Algorithms
| Algorithm | Parameter | Library |
|---|---|---|
| Zstandard | enc=zstd | zstandard |
| Gzip | enc=gzip | gzip |
| Brotli | enc=br | brotli |
| LZ4 | enc=lz4 | lz4 |
Common Causes
- Algorithm mismatch: URI says
enc=zstdbut data is gzip-compressed - Corrupted data: Compression stream was truncated or corrupted
- Double compression: Data was compressed twice
- Unsupported format: Using an algorithm not in the supported list
Diagnostic Steps
Check the declared algorithm:
textdata:application/json;enc=zstd;base64,... ^^^^^^^^Try decompressing with different algorithms:
pythonimport zstandard, gzip, brotli # Test each algorithm try: zstandard.ZstdDecompressor().decompress(data) except: pass
Resolution
- Verify algorithm: Ensure
enc=matches actual compression - Re-compress: Create a fresh compressed data URI
- Test locally: Verify decompression works before deploying
Example
import zstandard as zstd
import base64
import json
# Correct compression
metadata = {"type": "...", "name": "..."}
json_bytes = json.dumps(metadata).encode()
cctx = zstd.ZstdCompressor()
compressed = cctx.compress(json_bytes)
encoded = base64.b64encode(compressed).decode()
data_uri = f"data:application/json;enc=zstd;base64,{encoded}"EA006
Unsupported URI format
| Property | Value |
|---|---|
| Code | EA006 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| ERC-8004 Reference | URI format flexibility |
Description
The URI scheme is not recognized or supported by the parser.
Supported URI Formats
| Format | Example | Notes |
|---|---|---|
| IPFS | ipfs://Qm... | Content-addressed, immutable |
| Arweave | ar://... | Permanent storage |
| HTTPS | https://... | Standard web URL |
| HTTP | http://... | ⚠️ Insecure, not recommended |
| Data URI (base64) | data:application/json;base64,... | Inline, immutable |
| Data URI (plain) | data:application/json,... | Inline, URL-encoded |
Common Unsupported Formats
# ❌ Unsupported schemes
ftp://example.com/metadata.json
file:///local/path/metadata.json
custom://my-protocol/metadata
# ❌ Malformed URIs
//example.com/metadata.json (missing scheme)
example.com/metadata.json (missing scheme)Resolution
Convert to a supported format:
// ✅ IPFS (recommended for immutability)
"ipfs://bafkreiabc123..."
// ✅ HTTPS (easy to update)
"https://api.myagent.com/metadata.json"
// ✅ Data URI (fully onchain)
"data:application/json;base64,eyJ0eXBlIjoi..."EA007
IPFS fetch failed
| Property | Value |
|---|---|
| Code | EA007 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| Gateways Tried | ipfs.io, cloudflare-ipfs.com, gateway.pinata.cloud |
Description
Failed to fetch content from all IPFS gateways. The content may not be pinned or available.
Common Causes
- Content not pinned: The CID exists but no node is serving it
- Gateway timeout: All gateways timed out (>10s each)
- Invalid CID: The CID format is incorrect
- Network issues: Temporary gateway unavailability
Diagnostic Steps
Test CID accessibility:
bash# Try multiple gateways curl -I "https://ipfs.io/ipfs/YOUR_CID" curl -I "https://cloudflare-ipfs.com/ipfs/YOUR_CID" curl -I "https://gateway.pinata.cloud/ipfs/YOUR_CID"Verify CID format:
bash# CIDv0 starts with Qm (46 chars) # CIDv1 starts with bafy... or bafk...Check pinning status on your pinning service dashboard
Resolution
Pin content: Use a pinning service (Pinata, Infura, web3.storage)
bash# Using Pinata CLI pinata pin ./metadata.jsonVerify pinning: Check that at least one gateway can serve the content
Consider alternatives: For critical agents, also host on HTTPS as backup
Recommended Pinning Services
| Service | Free Tier | Notes |
|---|---|---|
| Pinata | 1GB | Popular, reliable |
| web3.storage | 5GB | Filecoin-backed |
| Infura | Limited | Enterprise-grade |
| Filebase | 5GB | Multi-protocol |
EA008
HTTP fetch failed
| Property | Value |
|---|---|
| Code | EA008 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| Timeout | 10 seconds |
Description
Failed to fetch content from the HTTP/HTTPS URL. Server may be down, URL may be invalid, or there may be SSL/TLS issues.
Common Causes
- Server unavailable: 5xx errors, server down
- Resource not found: 404 error
- SSL certificate issues: Expired or invalid certificate
- Timeout: Server didn't respond within 10 seconds
- CORS/Access issues: Server blocks requests from indexer IP
Diagnostic Steps
Test URL accessibility:
bashcurl -v "https://your-url.com/metadata.json"Check HTTP status:
bashcurl -I "https://your-url.com/metadata.json" # Should return: HTTP/2 200Verify SSL certificate:
bashopenssl s_client -connect your-url.com:443 -servername your-url.com
Resolution
- Fix server issues: Ensure server is running and healthy
- Verify URL: Check for typos, ensure path is correct
- Fix SSL: Renew certificate, ensure proper chain
- Use CDN: For better reliability and global availability
- Consider IPFS: For immutable, decentralized hosting
Recommended Practices
| Practice | Benefit |
|---|---|
| Use HTTPS | Security, required for most use cases |
| Use CDN | Reliability, speed |
| Set proper headers | Content-Type: application/json |
| Monitor uptime | Detect issues early |
EA009
Arweave fetch failed
| Property | Value |
|---|---|
| Code | EA009 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| Gateway | arweave.net |
Description
Failed to fetch content from Arweave gateway. Transaction may not be confirmed or ID may be invalid.
Common Causes
- Transaction not confirmed: Arweave transactions can take minutes to hours
- Invalid transaction ID: Typo or incorrect format
- Gateway issues: Temporary unavailability
Diagnostic Steps
Check transaction status:
bashcurl "https://arweave.net/tx/YOUR_TX_ID/status"Try fetching content:
bashcurl "https://arweave.net/YOUR_TX_ID"
Resolution
- Wait for confirmation: New transactions need time to propagate
- Verify transaction ID: Check for typos
- Use alternative gateway:
https://ar-io.net/YOUR_TX_ID
EA010
Non-dict metadata root
| Property | Value |
|---|---|
| Code | EA010 |
| Severity | Error |
| Field | agentURI |
| Parse Result | Fails |
| ERC-8004 Reference | Metadata MUST be a JSON object |
Description
The parsed JSON is not an object (dict). ERC-8004 metadata must be a JSON object with key-value pairs, not an array or primitive value.
Common Causes
- Array instead of object:
[{"name": "..."}]instead of{"name": "..."} - Primitive value: Just a string
"hello"or number123 - Null value: The JSON is literally
null
Resolution
Ensure metadata is a JSON object:
// ❌ Invalid: Array
[{"name": "Agent", "description": "..."}]
// ❌ Invalid: Primitive
"Agent metadata"
// ✅ Valid: Object
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "Agent",
"description": "..."
}Agent Warnings (WA001-WA099)
Issues that don't prevent parsing but may affect functionality or interoperability. These SHOULD be fixed.
WA001
Missing required field: type
| Property | Value |
|---|---|
| Code | WA001 |
| Severity | Warning |
| Field | type |
| Parse Result | Succeeds |
| ERC-8004 Compliance | SHOULD (recommended) |
Description
The type field is missing from metadata. This field identifies the metadata schema version and helps parsers understand the format.
ERC-8004 Specification
Per the Agent Metadata Profile:
The
typefield is SHOULD (recommended) for schema identification. Omitting it reduces interoperability with explorers and tools.
Impact
- Explorers may not recognize the metadata format
- Schema validation may fail
- Future compatibility issues if format changes
Resolution
Add the type field:
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "My Agent",
"description": "..."
}API Response Example
{
"parse_status": {
"status": "warning",
"warnings": [
{
"code": "WA001",
"field": "type",
"message": "Missing required field: type"
}
]
}
}WA002
Invalid type field value
| Property | Value |
|---|---|
| Code | WA002 |
| Severity | Warning |
| Field | type |
| Parse Result | Succeeds |
| Expected Value | https://eips.ethereum.org/EIPS/eip-8004#registration-v1 |
Description
The type field exists but doesn't match the expected ERC-8004 schema URL.
Resolution
Use the standard type value:
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1"
}WA003
Missing required field: name
| Property | Value |
|---|---|
| Code | WA003 |
| Severity | Warning |
| Field | name |
| Parse Result | Succeeds |
| ERC-8004 Compliance | SHOULD (recommended) |
Description
The name field is missing. This is a SHOULD field per ERC-8004 and is essential for agent display in explorers.
Impact
- Agent displays as "Unknown" or "Unnamed" in explorers
- Poor user experience when browsing agents
- Reduced discoverability
Resolution
{
"name": "My Agent Name"
}Best Practices
| Practice | Example |
|---|---|
| Be descriptive | "DataAnalyst Pro" ✅ |
| Avoid generic | "Agent #123" ❌ |
| Keep it short | 3-50 characters |
WA004
Missing required field: description
| Property | Value |
|---|---|
| Code | WA004 |
| Severity | Warning |
| Field | description |
| Parse Result | Succeeds |
| ERC-8004 Compliance | SHOULD (recommended) |
Description
The description field is missing. Users won't understand what your agent does.
Resolution
{
"description": "A specialized AI agent that performs advanced data analysis on blockchain transactions, providing insights and anomaly detection."
}WA005
Invalid image URL format
| Property | Value |
|---|---|
| Code | WA005 |
| Severity | Warning |
| Field | image |
| Parse Result | Succeeds |
| ERC-8004 Compliance | SHOULD use absolute URI |
Description
The image field contains a URL that doesn't start with a valid scheme.
Valid Schemes
| Scheme | Example |
|---|---|
https:// | https://cdn.example.com/logo.png |
http:// | http://example.com/logo.png (⚠️ insecure) |
ipfs:// | ipfs://Qm.../logo.png |
ar:// | ar://tx_id |
data: | data:image/png;base64,... |
Invalid Examples
// ❌ Invalid: relative path
{ "image": "/images/logo.png" }
// ❌ Invalid: missing scheme
{ "image": "www.example.com/logo.png" }
// ❌ Invalid: local file
{ "image": "file:///path/to/logo.png" }Resolution
Use an absolute URL with a valid scheme:
{ "image": "https://cdn.example.com/agents/logo.png" }WA006
endpoints field is not an array
| Property | Value |
|---|---|
| Code | WA006 |
| Severity | Warning |
| Field | endpoints |
| Parse Result | Succeeds |
| ERC-8004 Compliance | MUST be array if present |
Description
The endpoints (or services) field exists but is not an array.
Resolution
{
"services": [
{ "name": "MCP", "endpoint": "https://..." },
{ "name": "A2A", "endpoint": "https://..." }
]
}WA007
Endpoint object is not valid
| Property | Value |
|---|---|
| Code | WA007 |
| Severity | Warning |
| Field | endpoints |
| Parse Result | Succeeds |
Description
An item in the endpoints (or services) array is not an object.
Resolution
Each service must be an object:
{
"services": [
{ "name": "MCP", "endpoint": "https://..." } // ✅ Object
]
}WA008
Missing endpoint URL field
| Property | Value |
|---|---|
| Code | WA008 |
| Severity | Warning |
| Field | endpoints |
| Parse Result | Succeeds |
Description
An endpoint object is missing the endpoint field (the actual URL).
Resolution
{
"name": "MCP",
"endpoint": "https://your-agent.com/mcp" // Required
}WA009
Empty endpoint URL value
| Property | Value |
|---|---|
| Code | WA009 |
| Severity | Warning |
| Field | endpoints |
| Parse Result | Succeeds |
Description
An endpoint has an empty string "" for the endpoint field.
Impact
Clients won't be able to connect to this endpoint.
WA010
registrations field is not an array
| Property | Value |
|---|---|
| Code | WA010 |
| Severity | Warning |
| Field | registrations |
| Parse Result | Succeeds |
Description
The registrations field exists but is not an array.
WA011
Registration object is not valid
| Property | Value |
|---|---|
| Code | WA011 |
| Severity | Warning |
| Field | registrations |
| Parse Result | Succeeds |
Description
An item in the registrations array is not an object.
WA012
Missing agentRegistry field
| Property | Value |
|---|---|
| Code | WA012 |
| Severity | Warning |
| Field | registrations |
| Parse Result | Succeeds |
| ERC-8004 Compliance | MUST if registrations present |
Description
A registration is missing the required agentRegistry field.
Resolution
{
"registrations": [
{
"agentId": 1,
"agentRegistry": "eip155:84532:0x8004a6090Cd10A7288092483047B097295Fb8847"
}
]
}WA013
Invalid agentRegistry format (should be CAIP-2)
| Property | Value |
|---|---|
| Code | WA013 |
| Severity | Warning |
| Field | registrations |
| Parse Result | Succeeds |
| Reference | CAIP-2 Specification |
Description
The agentRegistry field is not in CAIP-2 format.
Expected Format
{namespace}:{chainId}:{contractAddress}Examples
| Chain | CAIP-2 Format |
|---|---|
| Ethereum Mainnet | eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847 |
| Base Sepolia | eip155:84532:0x8004a6090Cd10A7288092483047B097295Fb8847 |
| Arbitrum One | eip155:42161:0x8004a6090Cd10A7288092483047B097295Fb8847 |
WA014
supportedTrust field is not an array
| Property | Value |
|---|---|
| Code | WA014 |
| Severity | Warning |
| Field | supportedTrust |
| Parse Result | Succeeds |
Description
The supportedTrust field exists but is not an array.
WA015
active field is not boolean
| Property | Value |
|---|---|
| Code | WA015 |
| Severity | Warning |
| Field | active |
| Parse Result | Succeeds |
Description
The active field should be a boolean (true or false), not a string or number.
Resolution
{
"active": true // ✅ Boolean
}{
"active": "true" // ❌ String
}WA016
x402Support field is not boolean
| Property | Value |
|---|---|
| Code | WA016 |
| Severity | Warning |
| Field | x402Support |
| Parse Result | Succeeds |
Description
The x402Support field should be a boolean.
WA020
Found 'endpoint' (singular), should be 'endpoints'
| Property | Value |
|---|---|
| Code | WA020 |
| Severity | Warning |
| Field | endpoint |
| Parse Result | Succeeds |
| Type | Common typo detection |
Description
The field endpoint (singular) was found but the spec uses services (or legacy endpoints) (plural).
Resolution
Rename endpoint to services and ensure it's an array:
{
"services": [...] // ✅ Plural, array
}WA021
Found 'registration' (singular), should be 'registrations'
| Property | Value |
|---|---|
| Code | WA021 |
| Severity | Warning |
| Field | registration |
| Parse Result | Succeeds |
| Type | Common typo detection |
Description
The field registration (singular) was found but the spec uses registrations (plural).
WA030
agentWallet must be CAIP-10 format
| Property | Value |
|---|---|
| Code | WA030 |
| Severity | Warning |
| Field | agentWallet |
| Parse Result | Succeeds |
| Reference | CAIP-10 Specification |
Description
The agentWallet endpoint is not in CAIP-10 format.
Expected Format
{namespace}:{chainId}:{address}Example
{
"name": "agentWallet",
"endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7"
}WA031
Using legacy 'endpoints' field (recommend migrating to 'services')
| Property | Value |
|---|---|
| Code | WA031 |
| Severity | Warning |
| Field | endpoints |
| Parse Result | Succeeds |
| ERC-8004 Compliance | Legacy field name (still supported) |
| Added | Jan 2026 (EIP-8004 field name migration) |
Description
The agent metadata uses the legacy endpoints field name instead of the current services field name. While both are supported for backward compatibility, services is the official field name per EIP-8004 January 2026 update.
Background
In January 2026, the official EIP-8004 specification updated the field name from endpoints to services to better align with industry terminology. The change only affects the top-level array field name; individual service objects still use the endpoint property for their URLs.
Impact
- Parsing: No impact - metadata parses successfully
- Compatibility: Full backward compatibility maintained
- Recommendation: Migrate to
servicesfor consistency with current spec
Resolution
Update the field name from endpoints to services:
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "My Agent",
- "endpoints": [
+ "services": [
{
"name": "MCP",
"endpoint": "https://mcp.myagent.com",
"version": "2025-06-18"
}
]
}Important: Only the array field name changes. Individual service object properties remain unchanged:
- ✅
"endpoint"property within service objects - Correct (unchanged) - ✅
"services"top-level array field - Recommended (new name) - ⚠️
"endpoints"top-level array field - Legacy (triggers WA031)
Migration Timeline
| Phase | Date | Status |
|---|---|---|
| Spec Updated | Jan 2026 | ✅ Complete |
| Parser Support | Jan 2026 | ✅ Complete (supports both) |
| Deprecation Timeline | TBD | No immediate deprecation planned |
Note: There is no immediate deprecation timeline. Both
servicesandendpointswill be supported indefinitely. This warning is purely informational to encourage migration to the current spec.
See Also
- Agent Metadata Standard - Field Migration
- Migration Guide (v1.x → v2.0)
- WA020 - Common typo: using singular
endpointinstead of plural
WA050
base64 URI contains plain JSON (malformed)
| Property | Value |
|---|---|
| Code | WA050 |
| Severity | Warning |
| Field | agentURI |
| Parse Result | Succeeds |
| Type | Malformed data URI |
Description
The URI declares ;base64 encoding but the content is actually plain JSON.
Example
# ❌ Claims base64 but content is plain JSON
data:application/json;base64,{"name":"Agent"}
# ✅ Either remove ;base64
data:application/json,{"name":"Agent"}
# ✅ Or actually base64-encode
data:application/json;base64,eyJuYW1lIjoiQWdlbnQifQ==WA051
Non-standard base64 data URI format
| Property | Value |
|---|---|
| Code | WA051 |
| Severity | Warning |
| Field | agentURI |
| Parse Result | Succeeds |
Description
The data URI uses a non-standard format but was successfully parsed.
Standard Format
data:application/json;base64,<base64-data>WA052
Non-standard plain data URI format
| Property | Value |
|---|---|
| Code | WA052 |
| Severity | Warning |
| Field | agentURI |
| Parse Result | Succeeds |
Description
The plain data URI uses a non-standard format.
Standard Format
data:application/json,<json-data>WA053
Plain JSON without URI scheme
| Property | Value |
|---|---|
| Code | WA053 |
| Severity | Warning |
| Field | agentURI |
| Parse Result | Succeeds |
Description
The metadata appears to be raw JSON without a URI scheme.
Resolution
Wrap in a data URI:
data:application/json,{"name":"Agent",...}WA054
UTF-8 decode error in base64 content
| Property | Value |
|---|---|
| Code | WA054 |
| Severity | Warning |
| Field | agentURI |
| Parse Result | Succeeds |
Description
The base64-decoded content is not valid UTF-8.
Resolution
Ensure your JSON is UTF-8 encoded before base64 encoding.
WA055
Invalid JSON in base64 content
| Property | Value |
|---|---|
| Code | WA055 |
| Severity | Warning |
| Field | agentURI |
| Parse Result | Succeeds |
Description
The base64-decoded content is not valid JSON.
WA056
Invalid JSON in plain data URI
| Property | Value |
|---|---|
| Code | WA056 |
| Severity | Warning |
| Field | agentURI |
| Parse Result | Succeeds |
Description
The plain data URI content is not valid JSON.
WA070
Metadata content does not match on-chain agentHash
| Property | Value |
|---|---|
| Code | WA070 |
| Severity | Warning |
| Field | agentHash |
| Parse Result | Succeeds |
| Reference | agentHash Extension |
Description
The computed hash of the metadata doesn't match the agentHash stored on-chain via the registry's setMetadata() function.
What This Means
- The metadata content has changed since the owner set the hash
- For HTTP/HTTPS URIs, this could indicate content tampering
- Owner may have updated metadata but forgot to update the hash
8004scan Extension
This uses the agentHash on-chain metadata key, which is an 8004scan-recommended extension for HTTP/HTTPS URI integrity verification.
// Set agentHash on-chain
bytes32 hash = keccak256(abi.encodePacked(canonicalJson));
registry.setMetadata(agentId, "agentHash", abi.encode(hash));Resolution
If you updated metadata intentionally: Update the on-chain hash
If you didn't update: Investigate potential content modification
Compute new hash:
pythonimport json from web3 import Web3 metadata = {...} canonical = json.dumps(metadata, sort_keys=True, separators=(',', ':')) hash = Web3.keccak(text=canonical).hex()
API Response Example
{
"parse_status": {
"warnings": [
{
"code": "WA070",
"field": "agentHash",
"message": "Metadata content does not match on-chain agentHash",
"expected_hash": "0x1234567890ab...",
"actual_hash": "0xabcdef123456..."
}
]
}
}WA071
Metadata content has changed since last sync
| Property | Value |
|---|---|
| Code | WA071 |
| Severity | Warning |
| Field | _contentIntegrity |
| Parse Result | Succeeds |
| Type | Backend change detection |
Description
The metadata content differs from the previously indexed version. This is a backend integrity check, not an ERC-8004 spec field.
What This Means
For HTTP/HTTPS URIs, the content at the URL has changed since the last sync.
Note
This is expected if you intentionally updated your metadata. The warning helps detect unintended changes.
WA080
Conflict between on-chain and off-chain metadata
| Property | Value |
|---|---|
| Code | WA080 |
| Severity | Warning |
| Field | Variable (e.g., agent_wallet) |
| Parse Result | Succeeds (using higher-priority value) |
| Type | Metadata conflict |
Description
On-chain metadata (from MetadataSet events) conflicts with off-chain metadata (from AgentURI JSON). The values are different, and the on-chain value takes precedence.
What This Means
You have set different values for the same field in:
- On-chain:
setMetadata(agentId, "agentWallet", ...) - Off-chain: AgentURI JSON file
Common Causes
- Metadata not synchronized: Updated on-chain but not off-chain (or vice versa)
- Migration in progress: Moving from off-chain to on-chain metadata
- Accidental override: Unintentionally set a conflicting value
Resolution
Choose one authoritative source and update the other to match:
Option 1: Use on-chain metadata (recommended)
// On-chain metadata takes precedence automatically
// Update off-chain JSON to match:
{
"agentWallet": "eip155:1:0x..." // Match on-chain value
}Option 2: Use off-chain metadata
// Clear on-chain metadata
registry.setMetadata(agentId, "agentWallet", "0x"); // Empty valueNote
This warning indicates data inconsistency, not a critical error. The agent will be indexed successfully using the on-chain value.
WA081
Contract state conflicts with on-chain metadata
| Property | Value |
|---|---|
| Code | WA081 |
| Severity | Warning |
| Field | Variable (e.g., agent_wallet) |
| Parse Result | Succeeds (using contract state value) |
| Type | Metadata conflict |
Description
Contract state (from getter functions like agentWallet()) conflicts with on-chain metadata (from MetadataSet events). The values are different, and the contract state takes precedence.
What This Means
The contract's authoritative state differs from the indexed metadata:
- Contract state:
agentWallet()getter returns value A - On-chain metadata:
setMetadata("agentWallet", value B)
Common Causes
- Stale metadata: On-chain metadata not updated after contract state change
- Indexing issue: Subgraph returned outdated contract state
- Empty metadata value: Metadata set to
0x(empty) but contract has valid value
Resolution
Most Common: Empty metadata value (not a real conflict)
// If you see this with offchain_value: ""
// This is likely an empty value issue (fixed in latest parser)
// No action needed - contract state is correctIf real conflict exists:
// Update on-chain metadata to match contract state
bytes memory value = abi.encode(contractState);
registry.setMetadata(agentId, "agentWallet", value);Note
Contract state is the highest priority source. This warning helps identify data inconsistencies but doesn't affect agent indexing.
Related
See Onchain Metadata Handling for complete merging algorithm.
WA082
agentWallet in on-chain metadata is deprecated (REMOVED)
| Property | Value |
|---|---|
| Code | WA082 |
| Status | REMOVED (Feb 2026) |
| Severity | |
| Field | agentWallet |
| Added | Jan 2026 (ERC-8004 v2) |
| Removed | Feb 2026 |
Description
This error code has been removed and is no longer generated.
The original description was incorrect. After reviewing the ERC-8004 contract implementation:
// In IdentityRegistryUpgradeable.sol:
// setMetadata() explicitly FORBIDS setting agentWallet
require(keccak256(bytes(metadataKey)) != RESERVED_AGENT_WALLET_KEY_HASH, "reserved key");
// setAgentWallet() stores the wallet in _metadata (on-chain storage)
$._metadata[agentId]["agentWallet"] = abi.encodePacked(newWallet);
emit MetadataSet(agentId, "agentWallet", "agentWallet", abi.encodePacked(newWallet));Key insight: The setAgentWallet() function itself stores the wallet address in on-chain metadata (_metadata mapping) and emits a MetadataSet event. Therefore:
agentWalletappearing in on-chain metadata (fromMetadataSetevents) is the correct behavior- It's impossible to set
agentWalletviasetMetadata()- the contract rejects it as a reserved key - The only way to set
agentWalleton-chain is viasetAgentWallet()or duringregister()
Why This Was Removed
The parser was incorrectly flagging all agents with on-chain agentWallet as using deprecated functionality, when in fact they were using the contract correctly via setAgentWallet().
See Also
- WA083: Still valid - flags
agentWalletin off-chain metadata (agentURI JSON), which IS deprecated
WA083
agentWallet in off-chain metadata is deprecated
| Property | Value |
|---|---|
| Code | WA083 |
| Severity | Warning |
| Field | agentWallet |
| Parse Result | Succeeds |
| Type | Deprecated field usage |
| Added | Jan 2026 (ERC-8004 v2) |
Description
The agent has agentWallet in the off-chain metadata (agentURI content). In ERC-8004 v2, agentWallet should only be set on-chain via the setAgentWallet() function.
What This Means
Off-chain agentWallet declarations are now treated as discovery hints only. The authoritative value is always the contract state set via setAgentWallet().
Resolution
- Remove
agentWalletfield from your agent metadata JSON - Ensure wallet is set on-chain via
setAgentWallet()
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "My Agent",
- "agentWallet": "eip155:1:0x742d35Cc...",
"services": [...]
}Note
The off-chain value is ignored for payment purposes. Contract state is authoritative.
Agent Info (IA001-IA099)
Recommendations and best practices. These MAY be addressed but are not required.
IA001
Missing recommended field: image
| Property | Value |
|---|---|
| Code | IA001 |
| Severity | Info |
| Field | image |
| Parse Result | Succeeds |
| ERC-8004 Compliance | MAY (optional) |
Description
The image field is not present. Agents without images display with a default placeholder.
Resolution
{
"image": "ipfs://Qm.../logo.png"
}IA002
Missing endpoints array (agent won't be reachable)
| Property | Value |
|---|---|
| Code | IA002 |
| Severity | Info |
| Field | endpoints |
| Parse Result | Succeeds |
Description
No endpoints array defined. Clients cannot connect to this agent.
IA003
Empty endpoints array (agent won't be reachable)
| Property | Value |
|---|---|
| Code | IA003 |
| Severity | Info |
| Field | endpoints |
| Parse Result | Succeeds |
Description
The endpoints array exists but is empty.
IA004
Missing registrations array (no on-chain link)
| Property | Value |
|---|---|
| Code | IA004 |
| Severity | Info |
| Field | registrations |
| Parse Result | Succeeds |
Description
No registrations array. Explorers can't verify the bidirectional link between metadata and on-chain identity.
IA005
Empty registrations array (no on-chain link)
| Property | Value |
|---|---|
| Code | IA005 |
| Severity | Info |
| Field | registrations |
| Parse Result | Succeeds |
Description
The registrations array exists but is empty.
IA006
Missing agentId (expected for first-time deployments)
| Property | Value |
|---|---|
| Code | IA006 |
| Severity | Info |
| Field | registrations |
| Parse Result | Succeeds |
Description
A registration is missing agentId. This is normal for first-time deployments since you don't know the tokenId before registration.
Resolution
Update metadata after registration to include the assigned agentId.
IA007
agentId is null (expected for first-time deployments)
| Property | Value |
|---|---|
| Code | IA007 |
| Severity | Info |
| Field | registrations |
| Parse Result | Succeeds |
Description
The agentId is explicitly set to null. Same as IA006.
IA008
Empty supportedTrust array (discovery-only mode)
| Property | Value |
|---|---|
| Code | IA008 |
| Severity | Info |
| Field | supportedTrust |
| Parse Result | Succeeds |
Description
Agent has no trust models configured. Operating in discovery-only mode.
IA009
Unknown trust model (may be future extension)
| Property | Value |
|---|---|
| Code | IA009 |
| Severity | Info |
| Field | supportedTrust |
| Parse Result | Succeeds |
Description
A trust model in the array is not in the known set.
Known Models
reputationcrypto-economictee-attestationsocial-graph
IA010
Found 'supportedTrusts' (plural), spec uses 'supportedTrust'
| Property | Value |
|---|---|
| Code | IA010 |
| Severity | Info |
| Field | supportedTrusts |
| Parse Result | Succeeds |
Description
Common typo. The spec uses singular supportedTrust.
IA020
MCP endpoint missing version field
| Property | Value |
|---|---|
| Code | IA020 |
| Severity | Info |
| Field | MCP |
| Parse Result | Succeeds |
| ERC-8004 Compliance | Version is SHOULD, not MUST |
Description
MCP endpoint doesn't specify a version.
Recommendation
{
"name": "MCP",
"endpoint": "https://...",
"version": "2025-06-18"
}IA021
MCP version is not in date format (YYYY-MM-DD)
| Property | Value |
|---|---|
| Code | IA021 |
| Severity | Info |
| Field | MCP |
| Parse Result | Succeeds |
| Valid Format | YYYY-MM-DD (e.g., 2025-06-18, 2025-11-25, 2026-01-29) |
| Reference | MCP Specification |
Description
MCP uses date-based versioning. The version field should be in YYYY-MM-DD format representing the protocol specification date. Any valid date from 2024 onwards is accepted.
Valid examples:
"2025-06-18"- June 2025 spec"2025-11-25"- November 2025 spec (latest as of writing)"2026-01-29"- Future spec date
Invalid examples:
"1.0.0"- Not a date format"2025/06/18"- Wrong separator"25-06-18"- Year not in 4-digit format
IA022
A2A endpoint missing version field
| Property | Value |
|---|---|
| Code | IA022 |
| Severity | Info |
| Field | A2A |
| Parse Result | Succeeds |
Description
A2A endpoint doesn't specify a version.
IA023
A2A version is not in semver format
| Property | Value |
|---|---|
| Code | IA023 |
| Severity | Info |
| Field | A2A |
| Parse Result | Succeeds |
| Valid Format | Semver: X.Y.Z or X.Y (e.g., 0.3.0) |
Description
A2A uses semantic versioning. The version field should be in semver format (major.minor.patch or major.minor).
Valid examples:
"0.3.0"- Current A2A spec version"1.0.0"- Future major version"0.4"- Without patch number
Invalid examples:
"v0.3.0"- Avoid 'v' prefix for A2A"latest"- Not a version number
IA024
A2A endpoint should use .well-known/agent-card.json path
| Property | Value |
|---|---|
| Code | IA024 |
| Severity | Info |
| Field | A2A |
| Parse Result | Succeeds |
Description
A2A endpoint doesn't use the recommended well-known path.
Recommendation
https://your-agent.com/.well-known/agent-card.jsonIA025
OASF endpoint has neither skills nor domains
| Property | Value |
|---|---|
| Code | IA025 |
| Severity | Info |
| Field | OASF |
| Parse Result | Succeeds |
Description
OASF endpoint exists but has no skills or domains defined.
IA026
OASF version is not in semver format
| Property | Value |
|---|---|
| Code | IA026 |
| Severity | Info |
| Field | OASF |
| Parse Result | Succeeds |
| Valid Format | Semver with optional 'v' prefix: X.Y.Z, vX.Y.Z, or X.Y |
| Reference | OASF Releases |
Description
OASF uses semantic versioning. The version field should be in semver format, with an optional 'v' prefix. Multiple major version lines are supported (0.7.x, 0.8.x, etc.).
Valid examples:
"0.8.0"- Without 'v' prefix"v0.8.0"- With 'v' prefix"0.8.3"- Latest 0.8.x version"0.7.4"- 0.7.x version line"1.0.0"- Future major version
Invalid examples:
"latest"- Not a version number"0.8"- Missing patch number (while technically valid semver, full version preferred)
IA027
Unknown OASF skill category
| Property | Value |
|---|---|
| Code | IA027 |
| Severity | Info |
| Field | OASF |
| Parse Result | Succeeds |
| Reference | OASF Taxonomy |
Description
A skill in the OASF endpoint is not in the known taxonomy.
IA028
Unknown OASF domain category
| Property | Value |
|---|---|
| Code | IA028 |
| Severity | Info |
| Field | OASF |
| Parse Result | Succeeds |
Description
A domain in the OASF endpoint is not in the known taxonomy.
IA040
HTTP/HTTPS URI is not content-addressed
| Property | Value |
|---|---|
| Code | IA040 |
| Severity | Info |
| Field | agentURI |
| Parse Result | Succeeds |
Description
Agent uses a mutable HTTP/HTTPS URL for metadata. Content at HTTP URLs can change without notice.
Why This Matters
- No built-in integrity verification
- Content can change between fetches
- Harder to audit historical state
Recommendations
- Use IPFS:
ipfs://Qm...for immutable content - Set agentHash: On-chain integrity verification
- Use data URIs: For small metadata (
data:application/json,...)
IA041
URL-decoded plain data URI
| Property | Value |
|---|---|
| Code | IA041 |
| Severity | Info |
| Field | agentURI |
| Parse Result | Succeeds |
Description
The data URI content was URL-encoded and had to be decoded.
IA050
Field value from contract state (on-chain metadata empty or not set)
| Property | Value |
|---|---|
| Code | IA050 |
| Severity | Info |
| Field | Dynamic |
| Parse Result | Succeeds |
Description
A metadata field is using the value from contract state because the on-chain metadata for this field is empty or not set.
This is not an error - ERC-8004 contracts don't provide a deleteMetadata() function, so setting a field to empty (0x or "") is the standard way to indicate "not set". When this happens, the contract state value (if available) is used as the fallback.
Common Scenarios
Scenario 1: Empty agentWallet on-chain metadata
- On-chain metadata:
{"key": "agentWallet", "value": "0x"} - Contract state:
agentWallet = 0x461a...(fromsetAgentWallet()) - Result: Uses contract state value
- Info:
IA050on fieldagent_wallet
Scenario 2: agentWallet not set in on-chain metadata
- On-chain metadata: No
agentWalletentry - Contract state:
agentWallet = 0x461a... - Result: Uses contract state value
- Info:
IA050on fieldagent_wallet
Why This Happens
ERC-8004 metadata hierarchy (highest to lowest priority):
- Contract state (hardcoded fields:
agentWallet,owner) - On-chain metadata (via
setMetadata()) - Off-chain metadata (from
agentURI)
When on-chain metadata is empty, contract state takes precedence without conflict.
Resolution
No action needed - this is informational only. The field value is correct.
If you want to explicitly set the value in on-chain metadata:
// Set agentWallet in on-chain metadata (optional)
registry.setMetadata(tokenId, "agentWallet", "0x461a76074596f080dfba414532ab51280611b8e6");However, agentWallet cannot be set via setMetadata() - it's a reserved field that must be set via setAgentWallet() with signature verification.
See Also
- WA081: Contract state conflicts with on-chain metadata (when both are non-empty)
- Metadata Handling Guide:
/docs/implementation/onchain-metadata-handling.md
Feedback Errors (EF001-EF099)
Critical issues in feedback parsing.
EF001
Invalid timestamp format
| Property | Value |
|---|---|
| Code | EF001 |
| Severity | Error |
| Field | timestamp |
| Parse Result | Uses current time |
Description
The timestamp field cannot be parsed as a Unix timestamp.
Expected Format
Unix timestamp in seconds (integer).
EF002
Failed to fetch offchain data
| Property | Value |
|---|---|
| Code | EF002 |
| Severity | Error |
| Field | feedbackURI |
| Parse Result | Partial success |
Description
Could not fetch the feedback's offchain data from feedbackURI.
Feedback Warnings (WF001-WF099)
WF001
Invalid timestamp (using current time)
| Property | Value |
|---|---|
| Code | WF001 |
| Severity | Warning |
| Field | timestamp |
| Parse Result | Succeeds |
Description
Revocation timestamp invalid. Using current time as fallback.
WF002
Feedback hash mismatch
| Property | Value |
|---|---|
| Code | WF002 |
| Severity | Warning |
| Field | feedbackHash |
| Parse Result | Succeeds |
Description
The computed hash of offchain data doesn't match feedbackHash on-chain.
WF003
Tag stored as hash (original not available)
| Property | Value |
|---|---|
| Code | WF003 |
| Severity | Warning |
| Field | tag |
| Parse Result | Succeeds |
Description
The indexed tag1 is stored as a keccak256 hash and the original value wasn't in offchain data.
Why This Happens
Indexed string parameters in Solidity events are stored as hashes. The original value should be provided in feedbackURI data.
Related Documentation
- Agent Metadata Standard - Full schema specification
- Agent Metadata Parsing - Parsing implementation guide
- Feedback Best Practices - Feedback handling
- Data URI Compression - Compression extension
Last Updated: 2026-02-06