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

  1. Strip or re-indent any lines starting with the comment marker before constructing the RawString
  2. Pass the value as a normal (non-raw) string so the encoder quotes/escapes it instead
  3. 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

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.