Skip to content

55 high silent truncation

Part VII: Ecosystem, Runtime & Agent-Specific | Challenge §55

55. Silent Data Truncation

Severity: High | Frequency: Common | Detectability: Hard | Token Spend: Medium | Time: Medium | Context: Low

The Problem

CLI tools that write to remote APIs often silently truncate field values that exceed API limits: descriptions > 255 chars, names > 64 chars, tag arrays > 10 items. The tool reports exit 0 and "ok": true, but the resource was created with silently truncated data. The agent has no way to know the intended values weren't fully stored.

$ tool create-issue \
  --title "This is a very long title that definitely exceeds the 64 character limit"

{"ok": true, "data": {"id": 123, "title": "This is a very long title that definitely"}}
# Exit 0. Title was truncated silently. Agent proceeds with wrong assumption.

Array truncation is worse — items are silently dropped:

$ tool tag-resource --id res_1 --tags a,b,c,d,e,f,g,h,i,j,k  # 11 tags, limit is 10
# k was dropped. Agent thinks all 11 tags were applied.

Impact

  • Data integrity violations completely invisible to the agent at operation time
  • Agent reasoning built on "confirmed" values that were actually altered
  • Downstream operations reference data that doesn't exist as expected

Solutions

Truncated fields MUST appear in warnings[]:

{
  "ok": true,
  "warnings": [
    {
      "code": "FIELD_TRUNCATED",
      "field": "title",
      "original_length": 71,
      "truncated_to": 41
    }
  ]
}

Better: reject at Phase 1 validation with field constraints from schema:

{ "name": "title", "type": "string", "max_length": 64 }
{ "name": "tags",  "type": "array",  "max_items": 10 }

For framework design: - Schema MUST declare max_length, max_items, max_bytes for all bounded fields; Phase 1 rejects inputs exceeding these limits - If backend silently truncates anyway, framework MUST compare returned vs sent value and inject FIELD_TRUNCATED warning automatically

Evaluation

Score Condition
0 Values silently truncated with ok: true and no warning; agent cannot detect the data loss
1 Some truncation warnings emitted as prose; not in warnings[] array; FIELD_TRUNCATED code absent
2 warnings[] includes FIELD_TRUNCATED entries with field, original_length, and truncated_to
3 Schema declares max_length/max_items for bounded fields; Phase 1 rejects inputs exceeding limits before execution

Check: Pass a value that exceeds the documented field length limit — verify the response includes a FIELD_TRUNCATED warning or a VALIDATION_ERROR rejection, never silent truncation.


Agent Workaround

Check warnings[] after every write operation; validate field lengths against schema before sending:

import subprocess, json

def run_and_check_truncation(cmd: list[str], sent_values: dict) -> dict:
    result = subprocess.run(cmd, capture_output=True, text=True)
    parsed = json.loads(result.stdout)

    if not parsed.get("ok"):
        return parsed

    # Check for truncation warnings
    warnings = parsed.get("warnings", [])
    truncated = [w for w in warnings if w.get("code") == "FIELD_TRUNCATED"]
    if truncated:
        for t in truncated:
            field = t.get("field")
            original = t.get("original_length")
            truncated_to = t.get("truncated_to")
            print(
                f"WARNING: Field '{field}' was truncated from {original} to {truncated_to} chars. "
                "The stored value differs from what was sent."
            )

    # Compare returned values to sent values for fields we care about
    data = parsed.get("data", {})
    for field, sent_val in sent_values.items():
        returned_val = data.get(field)
        if isinstance(sent_val, str) and isinstance(returned_val, str):
            if sent_val != returned_val and len(returned_val) < len(sent_val):
                print(
                    f"POSSIBLE SILENT TRUNCATION: '{field}' sent {len(sent_val)} chars, "
                    f"got back {len(returned_val)} chars — check API field limits."
                )

    return parsed

Pre-validate lengths from schema constraints before sending:

def validate_lengths(schema_cmd: dict, args: dict) -> None:
    for param in schema_cmd.get("parameters", []):
        name = param.get("name")
        max_len = param.get("max_length")
        if max_len and name in args:
            value = args[name]
            if isinstance(value, str) and len(value) > max_len:
                raise ValueError(
                    f"--{name} exceeds max_length {max_len}: {len(value)} chars"
                )

Limitation: If the tool silently truncates with no warnings[] and returns the truncated value as ok: true, the only detection is to compare the returned field value against the sent value — build this comparison into every write operation for fields known to have length limits