headroomlabs-ai/headroom · error · TypeError
remote Kompress response field 'compressed' must be a string
Error message
remote Kompress response field 'compressed' must be a string
What it means
Raised by the remote Kompress client when the HTTP response is a 2xx but its JSON `compressed` field is not a string (e.g. null, a number, or a nested object). The client explicitly type-checks the one field it cannot infer, because the rest of `KompressResult` falls back to word counts. It signals a server-side contract violation or a wrong URL serving a different JSON shape, not a client bug.
Source
Thrown at headroom/transforms/kompress_remote.py:197
target_ratio: float | None = None,
*,
allow_download: bool = True,
) -> KompressResult:
n_words = len(content.split())
if n_words < _MIN_WORDS:
return self._passthrough(content, n_words)
try:
resp = self._client.post(
self._url,
headers=self._headers,
json={"content": content, "target_ratio": target_ratio},
)
resp.raise_for_status()
data = resp.json()
compressed = data["compressed"]
if not isinstance(compressed, str):
raise TypeError("remote Kompress response field 'compressed' must be a string")
# Coerce the numeric/string metadata fields inside the fail-open guard.
# A 200 response with a malformed field (e.g. a non-numeric string, or
# an explicit JSON null: data.get returns None for a present key, and
# float(None)/int(None) raise) would otherwise escape uncaught and break
# the proxy request, defeating the fail-open contract this class promises.
result = KompressResult(
compressed=compressed,
original=content,
original_tokens=int(data.get("original_tokens", n_words)),
compressed_tokens=int(data.get("compressed_tokens", len(compressed.split()))),
compression_ratio=float(data.get("compression_ratio", 1.0)),
model_used=str(data.get("model_used", self.config.model_id)),
)
except Exception as e: # fail OPEN — never break the proxy on a bad endpoint
logger.warning("Remote Kompress failed (%s); passing through", e)
return self._passthrough(content, n_words)
# CCR stays PROXY-LOCAL: endpoint is stateless (enable_ccr=False), so weView on GitHub (pinned to 322425c43b)
Solutions
- Inspect the raw response: curl the endpoint with a sample payload and check `data["compressed"]` is a plain JSON string
- Align versions: deploy the remote Kompress server version whose response schema includes a string `compressed` field, or update the client config/URL to the correct endpoint
- If an intermediary (proxy/gateway) is rewriting responses, bypass or fix it so the origin JSON reaches the client intact
Example fix
# before
client = KompressRemote(config) # url points at /v1/summarize
# after
client = KompressRemote(config.model_copy(update={"url": "https://host/v1/kompress/compress"}))
# verify: curl -s $URL -d '{"content":"hi","target_ratio":0.5}' | jq -r '.compressed | type' # must print "string" Defensive patterns
Strategy: try-catch
Validate before calling
resp = client._client.post(client._url, json={"content": sample, "target_ratio": 0.5})
data = resp.json()
assert isinstance(data.get("compressed"), str), f"contract drift: {type(data.get('compressed'))}" Type guard
def is_valid_kompress_response(data: dict) -> bool:
return isinstance(data, dict) and isinstance(data.get("compressed"), str) Try / catch
try:
result = remote.compress(text, target_ratio=0.5)
except TypeError as e:
if "'compressed' must be a string" in str(e):
result = local_fallback(text) # or pass through uncompressed
else:
raise Prevention
- Add a startup health check that POSTs a sample payload and validates the response schema
- Pin client and server versions together; deploy them in lockstep
- Monitor for non-200/non-JSON responses from intermediaries in front of the Kompress service
When it happens
Trigger: POSTing `{"content": ..., "target_ratio": ...}` to `self._url` and receiving 200 with `{"compressed": null}`, `{"compressed": 123}`, a truncated proxy error page parsed as JSON with a non-string field, or pointing the client at an endpoint that returns a different schema.
Common situations: Version skew between the remote Kompress server and this client (server renamed the field or returns a structured result), a load balancer/gateway returning a JSON status object, or a typo'd `url` in the remote config that happens to hit another JSON API.
Related errors
- token endpoint returned non-JSON
- invalid pipeline config TOML: {0}
- recommendations file not found: {0}
- upstream request failed: {0}
- items_json must be JSON: {e}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/f407fa59752650cd.
Report an issue: GitHub.