toon-format/toon · error · TypeError
Raw string must not contain a line starting with "${COMMENT_
Error message
Raw string must not contain a line starting with "${COMMENT_MARKER}": ${JSON.stringify(value)} What it means
The TOON encoder wraps user strings marked as raw in RawString, whose contract is that their content is emitted verbatim (unquoted, unescaped). Since a line starting with the comment marker would otherwise be re-parsed as a comment on decode, the constructor rejects any raw string containing such a line. This guarantees round-trip safety of raw strings.
Source
Thrown at packages/toon/src/encode/raw-string.ts:20
import { BYTE_ORDER_MARK, COMMENT_MARKER } from '../constants.ts'
// Decoders silently strip a line whose first non-space character is the comment marker,
// and they remove a leading byte-order mark before making that test.
const COMMENT_LINE_PATTERN = new RegExp(`(?:^${BYTE_ORDER_MARK}?|\\n) *${COMMENT_MARKER}`)
/**
* Pre-formatted string that the encoder emits verbatim at a primitive value
* position, bypassing quoting, escaping, and number/keyword detection.
*
* Returned from a replacer for an object or array value, it is ignored and
* the container is encoded normally.
*/
export class RawString {
readonly value: string
constructor(value: string) {
if (COMMENT_LINE_PATTERN.test(value)) {
throw new TypeError(`Raw string must not contain a line starting with "${COMMENT_MARKER}": ${JSON.stringify(value)}`)
}
this.value = value
}
}
/** Values the encoder can emit at a primitive position. */
export type EncodablePrimitive = JsonPrimitive | RawString
/**
* Wraps a pre-formatted string for verbatim emission, typically returned from
* an encode `replacer`. Compose with `escapeString` to control quoting yourself.
*
* @param value The exact text to emit at the value position
* @returns A `RawString` marker honored at primitive value positions
*
* @example
* ```ts
* encode({ name: 'Ada', age: 30 }, {View on GitHub (pinned to 604eac266e)
Solutions
- Strip or re-indent any lines starting with the comment marker before constructing the RawString
- Pass the value as a normal (non-raw) string so the encoder quotes/escapes it instead
- Catch the TypeError and surface a clear message to the user about the offending line
Example fix
// before
const raw = new RawString("# heading\nvalue: 1")
// after
const raw = new RawString("\\# heading\nvalue: 1") // or a normal string: toon.encode("# heading\nvalue: 1") Defensive patterns
Strategy: validation
Validate before calling
function canBeRawString(s: string): boolean {
return !s.split('\n').some(line => line.startsWith('#')) // replace '#' with your COMMENT_MARKER
} Type guard
function isSafeRawString(s: string): s is string {
return !COMMENT_LINE_PATTERN.test(s)
} Try / catch
try {
const raw = new RawString(userText)
} catch (e) {
if (e instanceof TypeError && e.message.includes('line starting with')) {
// fall back to quoting/escaping the value normally
}
throw e
} Prevention
- Sanitize comment-like lines before creating raw strings
- Prefer normal strings unless you specifically need verbatim emission
- Unit-test any user-supplied content routed through RawString
When it happens
Trigger: Calling `new RawString(value)` where any line of `value` begins with the comment marker (e.g. '#'). The check is COMMENT_LINE_PATTERN.test(value), so even embedded multi-line strings containing a comment-like line fail.
Common situations: Developers embedding configuration text, log excerpts, or template content that contains comment lines into raw strings for lossless encoding; copy-pasting text files with comments into raw strings.
AI-assisted analysis of toon-format/toon@604eac266e (2026-08-31).
Data as JSON: /api/errors/2dfeb00c4953b979.
Report an issue: GitHub.