Skip to content

--json flag rejects valid JSON when string values contain \n escapes #22

@sud0n1m

Description

@sud0n1m

The --json flag (both inline and @filename) rejects perfectly valid JSON whenever a string value decodes to a character including U+000A, even when the JSON source uses the spec-compliant \n escape.

Repro

# Build a valid JSON file using Python's json.dumps (newline escaped as \n)
python3 -c 'import json; open("/tmp/escaped.json","w").write(json.dumps({"id":"x","name":"x","type":"COMPONENT","settings":{},"parts":{"html":"line1\nline2"}}))'

# Python parses it without issue — confirming the JSON is well-formed
python3 -c 'import json; print(json.load(open("/tmp/escaped.json")))'
# → {'id': 'x', ..., 'parts': {'html': 'line1\nline2'}}

# cio rejects it
cio api /v1/environments/216574/ds/nodes -X POST --json @/tmp/escaped.json --dry-run
# → {"error":true,"code":"VALIDATION_ERROR","message":"JSON string value contains control character at position 5 (U+000A) (from file /tmp/escaped.json)","details":{"flag":"--json"}}

Per RFC 8259 §7, \n inside a string is the correct way to encode a literal newline. The CLI is validating the decoded string value for control chars rather than the JSON source, which makes it impossible to pass HTML, Carta markup, or any other multi-line content via --json without first collapsing newlines to spaces.

Expected

Treat input as valid JSON whenever it parses as valid JSON. If there's a security/safety concern with raw control chars hitting downstream APIs, surface it as a warning or add an explicit opt-in flag (--trust-json or --no-control-char-check), but don't break valid JSON by default.

Workaround (current)

Collapse HTML / multi-line content to a single line before passing to --json. This is what the in-app and Design Studio workflows have to do today.

Confirmed on @customerio/cli@0.0.5 (latest as of 2026-05-14).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions