agalwood/Motrix · error · RangeError

${label} JSON must not exceed ${maxJsonLength} characters

Error message

${label} JSON must not exceed ${maxJsonLength} characters

What it means

After the value passes the flat-string-record check, it is serialized with `JSON.stringify` and the resulting string must be at most `MAX_ERROR_DETAIL_PARAMS_JSON_LENGTH` (2048) characters. This bound matches the SQLite column width so the serialized blob fits. Throws this `RangeError` on overflow.

Source

Thrown at src/core/inspector-activity/validators.ts:153

  }
}

function assertBoundedDetailParams(
  value: Record<string, string> | null,
  label: string,
  maxJsonLength: number
): void {
  if (value === null) return
  if (
    typeof value !== 'object' ||
    Array.isArray(value) ||
    Object.values(value).some((entry) => typeof entry !== 'string')
  ) {
    throw new RangeError(`${label} must be a flat string record`)
  }
  const serialized = JSON.stringify(value)
  if (serialized.length > maxJsonLength) {
    throw new RangeError(
      `${label} JSON must not exceed ${maxJsonLength} characters`
    )
  }
}

export function validateHistoryEventInput(input: TaskHistoryEventInput): void {
  assertTaskId(input.taskId)
  assertPositiveSafeInteger(input.eventOrdinal, 'eventOrdinal')
  assertBoundedText(input.eventKey, 'eventKey', MAX_EVENT_KEY_LENGTH)
  assertBoundedText(
    input.runtimeGeneration,
    'runtimeGeneration',
    MAX_EVENT_KEY_LENGTH
  )
  assertPositiveSafeInteger(input.occurredAt, 'occurredAt')
  assertNonNegativeSafeInteger(input.occurredMonotonicMs, 'occurredMonotonicMs')
  if (!EVENT_KIND_VALUES.has(input.kind)) {
    throw new RangeError('kind is not a legal history event kind')

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Trim each param value to a per-key cap (e.g. 256 chars) before serialization.
  2. Drop low-value keys and keep only those referenced by the i18n message template.
  3. If the detail genuinely needs more space, persist it elsewhere and reference it by id in `errorDetailKey`.
  4. Compute `JSON.stringify(...).length` at the producer and prune until under 2048.

Example fix

// before
event.errorDetailParams = { stack: err.stack }  // multi-KB
// after
event.errorDetailParams = err.stack ? { stack: err.stack.slice(0, 1024) } : null
Defensive patterns

Strategy: validation

Validate before calling

const MAX = 2048
function fitDetailParams(params: Record<string, string>): Record<string, string> | null {
  const out = { ...params }
  while (JSON.stringify(out).length > MAX) {
    const longest = Object.keys(out).sort((a, b) => out[b].length - out[a].length)[0]
    if (!longest) return null
    out[longest] = out[longest].slice(0, Math.floor(out[longest].length / 2))
  }
  return out
}

Prevention

When it happens

Trigger: An `errorDetailParams` object whose JSON form exceeds 2048 chars — many keys, long values, or a few long URLs. E.g. storing a stack trace, a full request body, or a list of peer addresses as a single param value.

Common situations: Forwarding a verbose engine error payload (full request URL, headers, peer list) into params; accumulating params across retries without trimming.

Related errors


AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12). Data as JSON: /api/errors/2cde7f0d3f0bebdc. Report an issue: GitHub.