gchq/CyberChef · error · OperationError

Unable to parse JSON to CSV: ${err.toString()}

Error message

Unable to parse JSON to CSV: ${err.toString()}

What it means

Thrown by JSON to CSV after BOTH conversion attempts fail: the primary toCSV() and a fallback that flattens the structure and retries. The error captures whichever exception the fallback path raised (flatten() or toCSV(true)), reported via err.toString().

Source

Thrown at src/core/operations/JSONToCSV.mjs:104

        // Record values so they don't have to be passed to other functions explicitly
        this.cellDelim = cellDelim;
        this.rowDelim = rowDelim;
        this.flattened = input;
        if (!(this.flattened instanceof Array)) {
            this.flattened = [input];
        }

        try {
            return this.toCSV();
        } catch (err) {
            try {
                this.flattened = flatten(input);
                if (!(this.flattened instanceof Array)) {
                    this.flattened = [this.flattened];
                }
                return this.toCSV(true);
            } catch (err) {
                throw new OperationError("Unable to parse JSON to CSV: " + err.toString());
            }
        }
    }

    /**
     * Correctly escapes a cell's contents based on the cell and row delimiters.
     *
     * @param {string} data
     * @param {boolean} force - Whether to force conversion of data to fit in a cell
     * @returns {string}
     */
    escapeCellContents(data, force=false) {
        if (data !== "string") {
            const isPrimitive = data == null || typeof data !== "object";
            if (isPrimitive) data = `${data}`;
            else if (force) data = JSON.stringify(data);
        }

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Pre-shape the input into an array of flat, uniformly-keyed objects.
  2. Use JQ or JSONata upstream to project only scalar fields before conversion.
  3. Remove or stringify nested values so flattening produces leaf scalars.
  4. Confirm the input is actually JSON (not CSV/TSV) before this operation.

Example fix

// before: nested object that cannot be tabulated
chef.JSONToCSV({ user: { name: 'Ann', addr: { city: 'X' } } });
// after: flatten to scalar fields first
chef.JSONToCSV([{ name: 'Ann', city: 'X' }]);
Defensive patterns

Strategy: validation

Validate before calling

function normaliseForCsv(parsed) {
  const arr = Array.isArray(parsed) ? parsed : [parsed];
  return arr.map(o =>
    Object.fromEntries(Object.entries(o).map(([k, v]) =>
      [k, (v !== null && typeof v === 'object') ? JSON.stringify(v) : v]))
  );
}

Type guard

function isTabulatable(parsed) {
  const arr = Array.isArray(parsed) ? parsed : [parsed];
  return arr.every(o => o && typeof o === 'object' &&
    Object.values(o).every(v => v === null || typeof v !== 'object'));
}

Try / catch

try {
  return chef.JSONToCSV(input);
} catch (e) {
  if (/Unable to parse JSON to CSV/.test(e.message))
    throw new Error('Flatten the JSON to an array of scalar-field records first');
  throw e;
}

Prevention

When it happens

Trigger: Input JSON that is neither a flat record nor an array of flat records, where flattening still yields something toCSV cannot serialise: a scalar primitive at the top level, a structure with circular references, or a record whose flattened cells still contain nested objects/arrays the formatter rejects.

Common situations: Trying to convert a single nested object or a deeply-nested/ragged array of objects. Passing already-CSV text by mistake. Objects containing mixed array/object leaf values that do not flatten cleanly.

Understand the failure class

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/229a3c85e89736cb. Report an issue: GitHub.