attachment_unreachable

An attachment URL could not be downloaded: an error status, an empty file, or no answer within 20 seconds. Nothing was sent.

HTTP 422The request was understood but refused as sent. Change it before retrying.

When it fires

Repull tried to download one of the attachments and could not get the file. index and field name which one, and message says what happened:

  • the URL answered with an error status, such as 403 from an expired signed URL or 404;
  • the URL answered with an empty body;
  • the server did not answer within 20 seconds, or the connection failed.

Every file is checked before anything is delivered, so nothing was sent to the guest.

Response shape

Every Repull error follows the same envelope. The code is stable and safe to switch on.

{
  "error": {
    "code": "attachment_unreachable",
    "message": "Attachment 0: the URL returned HTTP 403. Nothing was sent.",
    "fix": "Make sure the URL is publicly readable (a signed URL must not have expired), then send again.",
    "docs_url": "https://repull.dev/docs/errors/attachment_unreachable",
    "request_id": "req_01J5X7Y8Z9ABCDEF12345678",
    "field": "attachments[0]",
    "channel": "airbnb",
    "index": 0
  }
}

How to fix

  1. Open the URL named by `index` without any cookies or login, for example with `curl -I`. It must return 200 and the file itself.
  2. If it is a signed URL, generate a fresh one just before the send; an expired signature answers 403.
  3. Make sure the URL points at the file, not at a web page that links to it.
  4. Send the request again with a new `Idempotency-Key`. A 422 is stored against the key it was sent with, so reusing that key replays the same refusal.

Examples

curl

# Check the file is publicly downloadable first
curl -I "https://cdn.example.com/parking-map.jpg"
# → HTTP/2 200, content-type: image/jpeg

curl -X POST https://api.repull.dev/v1/conversations/164743/messages \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "Here is the parking map.", "attachments": [{"url": "https://cdn.example.com/parking-map.jpg"}]}'

TypeScript

const res = await fetch('https://api.repull.dev/v1/conversations/164743/messages', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.REPULL_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ message: 'Here is the parking map.', attachments }),
})

if (res.status === 422) {
  const { error } = await res.json()
  if (error.code === 'attachment_unreachable') {
    // error.index names the file; regenerate its signed URL and send again
    console.warn(`Could not download attachment ${error.index}: ${error.message}`)
  }
}

If you're an AI agent

Repull could not download one attachment (error status, empty file or timeout). Nothing was sent. Check the URL named by `index` is publicly downloadable (regenerate an expired signed URL) and send again.

Hit an error that isn't covered? Email hello@repull.dev with the request id from the response headers.

AI