Delays and timeouts on ExecuteMailMergeOnlineRequest

We are doing mailmerge to create documents.
but the requests are failing or taking more than 10 minutes to timeout.

our client_id is 8f6fd319-a34d-4abf-8550-1b8751da0a57

How can we debug this, or can you investigate on your side what is the cause.

@VOGSY_service1

Understanding the Issue

ExecuteMailMergeOnlineRequest (Aspose.Words Cloud) can take a long time when:

Possible Cause Effect
Large source document (size > 10 MB) More data to read, parse and process.
Very large data source (thousands of rows / many images) Each record adds processing time; memory consumption grows.
Complex mail‑merge fields (nested fields, IF/ASK etc.) Additional evaluation per record.
Network latency / low bandwidth The request body (document + data) is streamed to the server, increasing overall time.
Default client timeout (10 min) The API aborts the call even if the server is still working.

Below are steps you can take to diagnose and mitigate the timeout.


:one: Enable Detailed Logging on the Client

Add a logger to capture request/response timing.
For the .NET SDK for example:

var config = new Configuration
{
    // Your client credentials
    ClientId = "8f6fd319-a34d-4abf-8550-1b8751da0a57",
    ClientSecret = "<your‑secret>",

    // Enable detailed logs
    Debug = true,
    DebugFile = "aspose_debug.log"
};

var wordsApi = new WordsApi(config);

// Your mail‑merge call
var request = new ExecuteMailMergeOnlineRequest(
    document: File.OpenRead("Template.docx"),
    data: File.OpenRead("Data.xml"),
    // optional: set a higher timeout (in seconds)
    timeout: 3600   // 1 hour
);
var response = wordsApi.ExecuteMailMergeOnline(request);

The generated aspose_debug.log will contain:

  • Request start/end timestamps
  • Size of the uploaded document & data file
  • Server‑side processing time (returned in the X-Processing-Time header)

Review the log to pinpoint whether the delay occurs before the request reaches the server (upload) or after (processing).


:two: Check the Size of Your Payload

  • Document – keep it under 10 MB when possible.
  • Data – if you are sending a huge XML/JSON (e.g., > 50 MB) consider splitting it into smaller batches.

Tip: Compress the source document (.docx is already a ZIP container) and the data file before uploading, then decompress on the server‑side using the zip parameter of the API.


:three: Use Asynchronous Batch Processing

If you have many records (e.g., > 5 000 rows), split the job into several smaller mail‑merge calls, or switch to the Background Job API:

var request = new CreateMailMergeJobRequest(
    document: File.OpenRead("Template.docx"),
    data: File.OpenRead("DataSmallChunk.xml")
);
var job = wordsApi.CreateMailMergeJob(request);
// Poll job status until Completed, then download the result

Background jobs run on a separate worker pool and are not bound by the 10‑minute client timeout.


:four: Increase the Client‑Side Timeout

The SDKs allow you to specify a custom timeout (in seconds).
For Java:

WordsApi api = new WordsApi(clientId, clientSecret);
api.getApiClient().setReadTimeout(3600_000); // 1 hour

(Replace the default 600 000 ms → 10 min.)
Note: The server itself still has a processing limit; an extremely large merge may still be aborted on our side.


:five: Verify Service Health

Occasionally the Aspose Cloud service may experience a temporary slowdown.
You can check the current status on the Aspose Cloud Status page:
https://status.aspose.cloud

If the status shows “All Systems Operational”, the delay is most likely payload‑related.


:six: What to Provide for a Deep‑Dive Investigation

If after the steps above the problem persists, open a support ticket with the following information:

Item Why We Need It
Exact request payload (document & data files) – preferably a reduced sample that reproduces the issue. Allows us to reproduce the processing time on our end.
SDK language & version (e.g., Aspose.Words‑Cloud SDK for .NET 22.7). Determines which client‑side timeout is applied.
Full debug log (as shown in step 1). Shows network latency and server‑side timing.
Number of records / size of data source. Helps to estimate expected processing time.
Any custom mail‑merge field logic (IF/ASK, image insertion, etc.). Complex fields can dramatically increase CPU usage.

Please submit the ticket via the Aspose Cloud Support Center and attach the items above. Our backend team will trace the request using the provided client_id and give you a concrete root‑cause analysis.


:seven: Quick Checklist

  • [ ] Enable SDK debug logging and capture timestamps.
  • [ ] Reduce document and data file size, or split into batches.
  • [ ] Switch to background‑job API for very large merges.
  • [ ] Increase client‑side timeout if needed.
  • [ ] Verify Aspose Cloud service health.
  • [ ] If still failing, raise a support ticket with the items listed in section 6.

References

Feel free to follow the checklist and let us know the outcome. If you need further assistance, just reply with the requested details, and we’ll investigate the request on our side.

Happy coding! :rocket:

I am sorry to hear it.
There are some cases for the behavior.

  1. API is too slow (run any API request from tests)
  2. Mail merge operation is too slow (run mail merge request from tests)
  3. Your document mail merging is too slow (run mail merging with simpler document)

If it is the cases #1 or #2, please inform us.
If it is the case #3, you could send the document and we’ll analyze it.
Or you could do it yourself:

  1. simplify your template until the issue disappears.
  2. add and remove different parts of the template to localize the source of the issue.
  3. optimize your template to fix it.

After some more investigating and debugging we pinpointed the issue a bit further.

here is the stacktrace of the error:

File "/workspace/src/shared/infra/microsoft_data_in_document_merger.py", line 51, in merge_data_in_document
    aspose_api_client = WordsApi(
                        ^^^^^^^^^
  File "/workspace/lib/asposewordscloud/apis/words_api.py", line 67, in __init__
    data = self.get_public_key(GetPublicKeyRequest())
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspace/lib/asposewordscloud/apis/words_api.py", line 12543, in get_public_key
    data = self.get_public_key_with_http_info(request, **kwargs)  # noqa: E501
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspace/lib/asposewordscloud/apis/words_api.py", line 12585, in get_public_key_with_http_info
    return request.deserialize_response(self.api_client, self.api_client.call_api(
                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspace/lib/asposewordscloud/api_client.py", line 406, in call_api
    return self.__call_api(resource_path, method,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspace/lib/asposewordscloud/api_client.py", line 165, in __call_api
    self.request_token()
  File "/workspace/lib/asposewordscloud/api_client.py", line 145, in request_token
    response_data = self.request(
                    ^^^^^^^^^^^^^
  File "/workspace/lib/asposewordscloud/api_client.py", line 449, in request
    return self.rest_client.POST(url,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspace/lib/asposewordscloud/rest.py", line 281, in POST
    return self.request("POST", url,
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/workspace/lib/asposewordscloud/rest.py", line 186, in request
    r = self.pool_manager.request(
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/urllib3/_request_methods.py", line 143, in request
    return self.request_encode_body(
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/urllib3/_request_methods.py", line 278, in request_encode_body
    return self.urlopen(method, url, **extra_kw)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/urllib3/poolmanager.py", line 459, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/urllib3/connectionpool.py", line 871, in urlopen
    return self.urlopen(
           ^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/urllib3/connectionpool.py", line 871, in urlopen
    return self.urlopen(
           ^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/urllib3/connectionpool.py", line 871, in urlopen
    return self.urlopen(
           ^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/urllib3/connectionpool.py", line 841, in urlopen
    retries = retries.increment(
              ^^^^^^^^^^^^^^^^^^
  File "/layers/google.python.pip/pip/lib/python3.12/site-packages/urllib3/util/retry.py", line 519, in increment
    raise MaxRetryError(_pool, url, reason) from reason  # type: ignore[arg-type]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.aspose.cloud', port=443): Max retries exceeded with url: /connect/token (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x3e8c9d4de720>, 'Connection to api.aspose.cloud timed out. (connect timeout=None)'))

It seems that we are getting connection retries while retrieving a token.

This seems to originate from the request_token method of the ApiClient object.

We have now updated this code:

        # perform request and return response
        response_data = self.request(
            'POST', url, query_params=[], headers=header_params,
            post_params=form_params, body=None,
            _preload_content=True,
            _request_timeout=(2,30))    # this was None, but this seems to cause timeouts 

We started experiencing this issue on August 28, around noon.

Our change seems to have mitigated the issue, but we will keep an eye on it for the coming days.

Was there something on the aspose side that can explain why this started occuring?

Alexander

I just noticed the newer version of the library has some changes in this code. We will first update to the latest version and continue testing.

I will contact the responsible team to check why getting a token fails with a timeout

@yaroslaw.ekimov We are also facing the same issue with obtaining a token since the past few days, can you please update us on whether there has been some changes to the endpoint and do we need to update the library in that case:

Error: HTTPSConnectionPool(host='api.aspose.cloud', port=443): Max retries exceeded with url: /connect/token (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0xfffe34a1dca0>: Failed to establish a new connection: [Errno 111] Connection refused'))"

We have been facing a lot of issues using the Aspose Cloud services (Slides) from the past week which is causing a lot of problem to our clients. Can you update whether there is some issue in the service and by when can we expect it to work in a stable manner?

Hey @VOGSY_service1 , we tried the same update that worked for you but we are still getting the timeout error. Are you able to use the service with the changes that you have made? For us the /connect/token endpoint is not responding at all.

please share your client id I send it to the billing team

The billing team asked me if you are still getting those timeouts.

@yaroslaw.ekimov I am still facing this issue. In fact I am not even able to open the Aspose Dashboard to check my account. The containerize login which allows me to login is not opening ( I have checked the network logs for the request which are failing).
Here is my client id, please fix the issue as fast as possible since our customers are complaining:

Client Id - 2f243052-b98b-4200-b4bf-7fab41158f39

I have shared all the info, especially about dashboard, they are looking into that issue.

@yaroslaw.ekimov Any timeline till when this will be resolved so we can inform our customers?

I haven’t got response from the responsible team yet.

@yaroslaw.ekimov Still not working, can you not provide a timeline atleast?

We are unable to find any issue with the service from our side. Could you try the mirror for api
https://api-mirror.aspose.cloud

@yaroslaw.ekimov We are using the asposeslidescloud library (version 24.12.0). For the mirror api, do we have to manually make the request or is there a way to do it using the library itself? If we need to manually make the request, can you share a code snippet that converts slides to png images?
Here is the code we are using right now with the library:

import asposeslidescloud
from asposeslidescloud.models.image_export_options import ImageExportOptions
from asposeslidescloud.models.export_format import ExportFormat
import os, shutil
from pptx import Presentation

CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
def calculate_aspect_fit(original_width, original_height, target_width, target_height):
    """
    Calculates the new dimensions to fit an original size into a target bounding box
    while preserving the original aspect ratio.

    :param original_width: Width of the original image/slide.
    :param original_height: Height of the original image/slide.
    :param target_width: The maximum width of the output image.
    :param target_height: The maximum height of the output image.
    :return: A tuple of (new_width, new_height) as integers.
    """
    original_ratio = original_width / original_height
    target_ratio = target_width / target_height

    if original_ratio > target_ratio:
        # Original is wider than the target box, so the new width is the target width
        new_width = target_width
        new_height = new_width / original_ratio
    else:
        # Original is taller than or equal to the target box, so the new height is the target height
        new_height = target_height
        new_width = new_height * original_ratio
        
    return int(round(new_width)), int(round(new_height))

# initialize Aspose.Slides Cloud instance.
configuration = asposeslidescloud.Configuration()
configuration.app_sid = CLIENT_ID
configuration.app_key = CLIENT_SECRET
slidesApi = asposeslidescloud.SlidesApi(configuration)

# load PPT file from local drive into Stream instance
fileName = "Prototyping presentation.pptx"
presentation = Presentation(fileName)
print(f"Number of slides in presentation: {len(presentation.slides)}")
num_pptx_slides = len(presentation.slides)
width = presentation.slide_width
height = presentation.slide_height
print(f"Slide dimensions are : width = {width}, height = {height}")
# Calculate new dimensions to fit the slide into a 1280x720 box
new_width, new_height = calculate_aspect_fit(width, height, 1280, 720)
print(f"New dimensions such that the slides fit into the canvas are: width = {new_width}, height = {new_height}")

with open(fileName, 'rb') as f:
    file = f.read()
    
options = ImageExportOptions()
options.width = new_width
options.height = new_height
options.show_hidden_slides = True

thread = slidesApi.convert(file, format=ExportFormat.PNG, options=options, fonts_folder="custom_fonts", is_async=True)

path = thread.get()
print(f"File converted to {path}")

Please share code snippet for making an equivalent call with the mirror api.

Regarding slides you better contact them via their forum, I can’t help with that product.

We were using version 22.2.0 of the aspose-words-cloud library. I noticed this was posting to “/connect/token”. The latest version posts to “/v4.0/words/connect/token”.

Is there a difference with that endpoint?

No, these endpoints are identical. We use different ones just for clarity with api usage.