REST API attachment upload returns 500 instead of 429 when Media rate limits the request

XMLWordPrintable

    • 1
    • Severity 3 - Minor

      Issue Summary

      When uploading multiple attachments to a Confluence Cloud page via the REST API (POST /wiki/rest/api/content/{pageId}/child/attachment), some requests receive a 500 Internal Server Error instead of the expected 429 Too Many Requests from the upstream Media service.

      The root cause is that the ExceptionConverter class does not have a mapping for AttachmentDataFileSystemException (which wraps the Media API's 429 response), so it defaults to 500 Internal Server Error. This causes two problems:

      1. The 429 status code is not surfaced to the API consumer
      1. The Retry-After header from the Media API response is lost, preventing the client from implementing proper backoff

      Additionally, some requests from Confluence to the Media API are missing required x-media-* headers (x-media-client-id, x-media-region, x-media-request-category, x-media-source-product), causing them to fall into a lower default rate limit bucket instead of the per-client bucket.

      A similar issue was previously identified and fixed in Jira: 

      The Confluence REST API attachment upload path needs the same treatment.

      Steps to Reproduce

      1. Use the REST API to upload a large number of attachments (e.g., 100+ small PNG files) to a single Confluence Cloud page in rapid succession:
         POST /wiki/rest/api/content/{pageId}/child/attachment
      2. Observe that some requests fail with 500 Internal Server Error

      Expected Results

      • If the Media API rate limits the request, the REST API should return 429 Too Many Requests with the Retry-After header preserved, allowing the client to implement proper backoff and retry.
      • All internal requests from Confluence to the Media API should include the required x-media-* headers so that rate limiting is applied against the correct per-client bucket.

      Actual Results

      The API returns 500 Internal Server Error with no Retry-After header. The client cannot distinguish between a transient rate limit and a genuine server error.

      Workaround

      There is no clean workaround. As a partial mitigation, API consumers can:

      • Add fixed delays between upload requests (reduces throughput significantly)
      • Parse the 500 response body for RateLimitedRequestError to detect rate limiting and implement manual backoff

              Assignee:
              Unassigned
              Reporter:
              Kyungmin Kim
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated: