Upload ‘works’ but the file is empty / not searchable
Uploading is two calls:POST /v1/files registers the file and returns a
signed_url; you then PUT the actual bytes to that URL.
- If you skip the PUT (or it failed), the file exists but has no content.
- The PUT goes to storage directly — don’t send your
Authorizationheader on it. - Send every header in the init response’s
required_headersexactly as given. They are signed, so a missing or altered one gets the PUT rejected.
upload_status is failed
Mesh checks the bytes after they land.upload_status becomes failed when:
- the file is over 50 MB (
max_size_bytesin the init response), or - the PUT’s
Content-Typedoesn’t match themime_typeyou registered.
embedding_status never ends in this case, so check upload_status too. Give
the loop a deadline as well: if the PUT never lands, upload_status stays
pending forever.
‘signed_url’ rejected / expired
Thesigned_url expires 15 minutes after you register the file. PUT your
bytes right away. If it expired, register the file again to get a
fresh URL.
Search returns nothing right after upload
Embedding is asynchronous. A file is only searchable onceembedding_status is ready.
- Poll
GET /v1/files/{file_id}untilembedding_statusisready(it movesqueued → processing → ready). - If it’s
failed, re-trigger withPOST /v1/files/embed(pass"wait": trueto block for small files). The file’supload_statusmust beready, and a file that failed can’t be re-queued for 30 minutes. - If
embed: falsewas set at upload, embedding never started — trigger it manually.
Search returns irrelevant or too few results
- Raise
top_k(1–50, default 5). - An over-restrictive
filter(metadata is exact match) ordate_from/date_towindow can exclude everything — loosen them. - A too-narrow
file_idslist restricts search to those files only; omit it to search all your files. - Metadata filters only match keys you set at upload time.
422 on upload
Check required fields onPOST /v1/files — file_name and mime_type (e.g.
application/pdf, text/plain, text/markdown). The mime_type also drives
file-type detection; an unsupported one is a 422.
400 on upload: key owner is not a valid UUID
RAG needs a key created in the dashboard. A key minted another way (for example with an admin key) has no user owner, and uploads with it return400.