mallow docs

Errors

The error format, every HTTP status the mallow API returns, the error codes it sets, and which failures are safe to retry.

The Error Format

A failed request returns a JSON body with one error object:

{ "error": { "message": "Invalid API key" } }
FieldPresentUse
error.messageAlwaysText for a log or a person. The wording can change
error.codeSometimesA stable name for the failure. See Error codes

These are real responses, captured on 12 October 2026 from requests sent without a valid key:

curl -i https://api.mallow.art/v1/artworks/trending
# HTTP/2 401
# {"error":{"message":"Invalid API key"}}

curl -i https://api.mallow.art/v2/auctions/So11111111111111111111111111111111111111112
# HTTP/2 401
# {"error":{"message":"Unauthorized"}}

Most errors carry no code

Only some /v1 errors set code. No /v2 error does. Decide on the HTTP status first, then on code when there's one, and never rely on code being present.

Some /v1 errors add fields:

  • A validation error adds error.details, the full list of problems. See VALIDATION_ERROR
  • Some errors add an info object beside error, with the values the request was about

Responses Without the Format

A few failures are returned before the request reaches mallow's handlers, and their body isn't JSON. Read the body as text before you parse it.

StatusWhenBody
400The body of a /v2 POST isn't valid JSONPlain text
415A /v2 POST without content-type: application/jsonPlain text
422The body of a /v2 POST is missing a required field, or a field has the wrong typePlain text naming the field
408A /v2 request ran longer than 15 secondsEmpty
404A /v2 path that doesn't existEmpty

HTTP Statuses

StatusMeaningWhat to do
400The request isn't valid, or what it asks for can't be done right now. Examples from /v2: Listing not found on a buy, Auction has not yet ended on a settle, User is not allowlisted on a bidRead message. Fix the request or read the current state again. Sending the same request again returns the same error
401The key is missing or not valid. /v1 returns Invalid API key in both cases. /v2 returns Unauthorized when no key was sent and Invalid API key when the key isn't recognisedCheck the x-api-key header. See Authentication
404The thing the request names doesn't exist. See 404Stop, or read the state again
408A /v2 request timed out after 15 secondsRetry
409A Magic Eden order changed after you got a quote. See 409Get a new quote
415, 422A /v2 request body was rejected. See Responses without the format. Bid or buy also returns 422 when the wallet has reached the listing's buy limitFix the request
429Over the rate limitWait for the window to end. See Rate limits and retries
500Something failed on mallow's side. On /v2 the message is always Internal server error. On /v1 it can name the causeRetry a read or a build after a pause. If it keeps failing, tell us
503A dependency wasn't available. The draw builders return this when chain state couldn't be read or the draw couldn't be simulated. The Magic Eden routes return it when they're busy or switched offRetry after a pause

The reference pages list 400, 401, 404, 409, 429 and 500. The API also returns the other statuses in this table.

404

OperationsA 404 means
Artwork by mint, Public profile by addressmallow has no artwork or user for that address. code is NOT_FOUND
The five account readsThe address holds an account of another type or another program. An address with no account at all is a 200 with account: null
Edition buyer statsThe mint has no listing
Raffle buyer stats, Buy raffle tickets, Claim raffle prizeThe raffle doesn't exist
Cancel offerThe buyer has no offer on that artwork
Bid or buyThe artwork has no listing or auction, or mallow hasn't indexed it
Schedule a bidThe artwork has no auction
Draw a Gumball, Draw a JellybeanThe machine doesn't exist

The other /v2 builders return a 400 for a missing listing, auction, offer or raffle, not a 404.

409

Only Buy on Magic Eden returns 409. The order's price, currency, expiry or escrow changed after the quote, or the total passed the limits you sent. The message starts with STALE_ORDER:. Request the quote again and show the buyer the new terms.

Error Codes

These are all the codes the public API sets. All four come from /v1.

CodeStatusReturned byMeaningWhat to do
VALIDATION_ERROR400Every /v1 POSTThe request body failed validationFix the request. message names the first problem and details lists them all
NOT_FOUND404Artwork by mint, Public profile by addressNo artwork or user for that addressStop. Check the address
RATE_LIMITED429Every /v1 operationThe key is over its limit for this minuteWait, then retry. A /v2 429 has the same message and no code
INTERNAL_ERROR500The /v1 artwork, event, reward and profile reads, except Trending artworksAn unexpected failure. message can name the causeRetry after a pause

Every other error has no code, including every 401.

A validation error has this shape. The values are placeholders:

{
  "error": {
    "message": "<field>: <problem>",
    "code": "VALIDATION_ERROR",
    "details": [
      {
        "location": "body",
        "issues": [{ "path": "<field>", "message": "<problem>" }]
      }
    ]
  }
}

Failures Inside a 200

Two groups of operations report a failure in a successful response. Check the body, not only the status.

A state read that finds nothing is also a 200, with null in place of the state. Treat that as a valid answer.

What Is Safe to Retry

CallSafe to repeatNotes
Any readYes
Any builder: /v2/tx/*, Bid or buy, the scheduled-bid builders, the draw buildersYesA build changes nothing on chain
Draw statusYes
Draw submitNoEach draw transaction is accepted once. A repeat returns an error for that transaction and no new information
Sending the same signed transaction to your RPCYesThe network accepts a signature once
Building again and sending the new transactionOnly after the first one expiredIf the first transaction landed, the second is a second purchase. Look up the first signature before you rebuild

Retry 408, 429, 500 and 503. Don't retry any other 4xx without changing the request. The quickstart has a retry helper.

On-Chain Failures

The API builds transactions and you run them. A transaction can build without error and still fail when you send it, and that failure comes back from your Solana RPC rather than from mallow.

It shows up in one of two places:

  • At send time. The RPC simulates the transaction first and rejects it, with the program logs in the error
  • After it lands. The signature's status carries an err, which confirmTransaction returns in value.err

Either way the error names the instruction that failed and a number:

{ "InstructionError": [2, { "Custom": 6002 }] }

Here 2 is the position of the instruction in the transaction, and 6002 is the error code of the program that instruction calls. The same number means different things in different programs, so find the program first. Its address is in the decoded transaction and in the logs. SDKs and programs lists mallow's.

mallow's programs number their own errors from 6000. Where to look a code up:

ProgramError list
Market, Auction, RewardsThe npm clients export every code and a lookup: getMallowMarketErrorMessage, getMallowAuctionErrorMessage, getMallowRewardsErrorMessage. See SDKs and programs
SweepstakegetMallowSweepstakeErrorMessage from @mallow-labs/mallow-sweepstake-sdk/generated
Gumballerrors.rs
Gumball Guarderrors.rs
Jellybeanerrors.rs

Common causes are a listing that sold or was cancelled between the build and the send, a wallet without enough funds for the price and fees, and an expired blockhash. For the last one, see Blockhash expiry.

Draws are the exception, because mallow sends them. A draw that fails simulation comes back from the submit call with an error and its logs. A draw that fails on chain shows up in the status call.

On this page