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 we

View on GitHub (pinned to 322425c43b)

Solutions

  1. Inspect the raw response: curl the endpoint with a sample payload and check `data["compressed"]` is a plain JSON string
  2. 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
  3. 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

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


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/f407fa59752650cd. Report an issue: GitHub.