Skip to content

ChangeRequestMicroClient.list() mutates class variable causing URL template to grow indefinitely #30

@Patryk-Janowski

Description

@Patryk-Janowski

Bug: ChangeRequestMicroClient.list() Mutates Class Variable Causing URL Template to Grow Indefinitely

Description

The list() method in ChangeRequestMicroClient mutates the shared class variable _endpoint, causing the URL template to grow with every call. After ~25 calls in a Prefect environment (used for managing split production environments), requests start failing with HTTP 414 (URI Too Long). When tested locally, failures occur after 100+ calls with either 414 or 431 (Request Header Fields Too Large) errors.

Root Cause

In microclients/change_request_microclient.py, _endpoint is defined as a class variable (line 10), but the list() method (lines 72–77) mutates it directly:

if(environment_id!=None):
    self._endpoint['list_next']['url_template'] = self._endpoint['list_next']['url_template'] + "&environmentId={environmentId}"
    self._endpoint['list_initial']['url_template'] = self._endpoint['list_initial']['url_template'] + "&environmentId={environmentId}"
if(status!=None):
    self._endpoint['list_next']['url_template'] = self._endpoint['list_next']['url_template'] + "&status={status}"
    self._endpoint['list_initial']['url_template'] = self._endpoint['list_initial']['url_template'] + "&status={status}"

Because _endpoint is shared across all instances, each invocation appends query parameters again, causing exponential growth of the URL template.

Impact

  • After ~25 consecutive list() calls, requests fail with HTTP 414 in a Prefect environment
  • Locally, failures occur after ~100–120 calls with 414 or 431
  • Affects any code that calls change_requests.list() repeatedly
  • The mutation persists for the lifetime of the class, impacting all future instances

Reproduction Steps

from splitapiclient.main import get_client

client = get_client({"apikey": "your_api_key"})
ENV_ID = "your_environment_id"

# After ~25 iterations, the endpoint URL template becomes extremely long
for i in range(30):
    cr = client.change_requests.list(environment_id=ENV_ID, status="REQUESTED")
    print(f"Call {i+1}: {len(client.change_requests._endpoint['list_initial']['url_template'])} chars")

Note: Depending on network configuration, the error may require ~120 iterations to reproduce.

After multiple calls, _endpoint['list_initial']['url_template'] looks like:

changeRequests?limit=100&environmentId={environmentId}&status={status}&environmentId={environmentId}&status={status}&environmentId={environmentId}&status={status}...

Expected Behavior

The URL template should remain constant. Query parameters should be passed via the HTTP client's parameter mechanism, not by mutating the template string.

Environment

  • Python version: 3.13 (also observed across 3.x)
  • splitapiclient version: 3.5.6
  • Production environment with high-frequency API calls

Additional Context

This is a critical production issue that causes failures after a relatively small number of calls. A proper fix should ensure that endpoint configuration is immutable or safely scoped per instance to avoid shared state mutations.

self._endpoint['list_next']['url_template'] = self._endpoint['list_next']['url_template'] + "&environmentId={environmentId}"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions