chenhg5/cc-connect · warning

max: send message: attachment not ready after %d retries

Error message

max: send message: attachment not ready after %d retries

What it means

The MAX API kept responding with an 'attachment not ready' error for every attempt in the send retry loop (attachmentReadyRetries attempts with exponential backoff), so the platform gives up. MAX returns this transient error when an attachment (uploaded media) is not yet processed on its CDN.

Source

Thrown at platform/max/max.go:1418

		resp.Body.Close()

		if resp.StatusCode == http.StatusOK {
			return nil
		}
		if isAttachmentNotReady(respBody) && attempt < attachmentReadyRetries {
			slog.Debug("max: attachment not ready, retrying", "attempt", attempt+1, "backoff", backoff)
			select {
			case <-ctx.Done():
				return ctx.Err()
			case <-time.After(backoff):
			}
			backoff *= 2
			continue
		}
		slog.Warn("max: send message failed", "status", resp.StatusCode, "chat", chatID, "body", string(respBody))
		return fmt.Errorf("max: send message: HTTP %d: %s", resp.StatusCode, respBody)
	}
	return fmt.Errorf("max: send message: attachment not ready after %d retries", attachmentReadyRetries)
}

func isAttachmentNotReady(body []byte) bool {
	return bytes.Contains(body, []byte("attachment.not.ready")) ||
		bytes.Contains(body, []byte("not.ready"))
}

func (p *Platform) getMe(ctx context.Context) (name string, id int64, err error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, p.apiBase+"/me", nil)
	if err != nil {
		return "", 0, err
	}
	p.setAuth(req)

	resp, err := p.client.Do(req)
	if err != nil {
		return "", 0, err
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Increase attachmentReadyRetries and/or the initial backoff in the retry loop
  2. Verify the attachment upload completed (poll the upload result) before sending the message
  3. Return a clear user-facing 'media is still processing, try again' message on this error
  4. Check MAX service status if this happens across many sends

Example fix

// before
return fmt.Errorf("max: send message: attachment not ready after %d retries", attachmentReadyRetries)
// after
return fmt.Errorf("max: send message: attachment not ready after %d retries (consider raising attachmentReadyRetries or delay before send)", attachmentReadyRetries)
Defensive patterns

Strategy: retry

Validate before calling

if uploaded, err := pollUploadComplete(ctx, fileID); err != nil || !uploaded { delayBeforeSend() }

Try / catch

if err := send(); err != nil && strings.Contains(err.Error(), "attachment not ready") {
	time.Sleep(2 * time.Second)
	err = send() // or increase attachmentReadyRetries
}

Prevention

When it happens

Trigger: Sending a message with a just-uploaded attachment while MAX is still processing it, and processing takes longer than the total retry window.

Common situations: Large video/image uploads during MAX CDN slowness; uploading and immediately sending in the same flow; MAX service degradation making 'not ready' persist beyond the retry budget.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/c1ceb519d0db1a70. Report an issue: GitHub.