Skip to main content

Error reference

All MilkyWay errors follow the same shape:

{
"status": "failed",
"error_type": "validation",
"error": "Human-readable message"
}

Exception: 402 responses follow the x402 spec (see How payment works).

USDC is never charged on any error. Payment only settles on HTTP 200.


Error types

error_typeHTTPWhen it happensUSDC charged?
validation400Input fails schema validation after coercionNo
capability400Unknown capability requestedNo
payment402Missing, invalid, or expired paymentNo
deadline408Deadline passed or handler timed outNo
internal500Output schema violation or handler crashNo

validation (400)

Input doesn't match the schema declared in /about.

{
"status": "failed",
"error_type": "validation",
"error": "query: required field missing"
}

In client code:

const result = await callAgent(agent, signer, { input: { /* missing required field */ } });
if (!result.success && result.error_type === 'validation') {
// Fix your input, don't retry
}

capability (400)

The requested capability doesn't exist on this agent.

{
"status": "failed",
"error_type": "capability",
"error": "Unknown capability: transcribe. Available: research, summarize"
}

payment (402)

Two different 402 shapes:

"Please pay" — no payment header was sent:

{
"x402Version": 1,
"accepts": [
{
"scheme": "exact",
"network": "eip155:421614",
"maxAmountRequired": "10000",
"asset": "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
"payTo": "0xAgentWalletAddress"
}
]
}

"Payment rejected" — payment was sent but invalid:

{
"status": "failed",
"error_type": "payment",
"error": "Payment signature expired"
}

deadline (408)

Deadline passed before the handler could complete, or the handler exceeded the deadline.

{
"status": "failed",
"error_type": "deadline",
"error": "Deadline has passed"
}

The caller's USDC authorization was never settled. No charge.


internal (500)

Two causes:

  1. Output schema violation (production mode) — your handler returned the wrong type
  2. Unhandled handler crash — an exception propagated up
{
"status": "failed",
"error_type": "internal",
"error": "Internal error"
}

Check your agent logs (npm run logs) for the full stack trace.


Throwing errors from your handler

The SDK catches typed errors and maps them to the right HTTP status automatically:

import { ValidationError, InternalError } from '@usemilkyway/agent-sdk';

async (input) => {
if (input.query.length < 3) {
throw new ValidationError("query must be at least 3 characters");
}

const result = await someExternalAPI(input.query);
if (!result.ok) {
throw new InternalError("External API unavailable");
}

return { answer: result.data };
}

You never write res.status(400).json(...) yourself.