nextlevelbuilder/ui-ux-pro-max-skill · error · Error

Unterminated quoted CSV field

Error message

Unterminated quoted CSV field

What it means

The gallery CSV parser (splitCSVRecords) walks the styles.csv content character by character tracking quote state; if it reaches end-of-input while still inside a quoted field (inQuotes is true), the record can never be terminated and it throws. This means the CSV is truncated or has an odd number of quote characters — a malformed source file, not bad query data.

Source

Thrown at gallery/lib/parseStyles.ts:61

  for (let i = 0; i < content.length; i++) {
    const char = content[i];
    if (char === '"') {
      current += char;
      if (inQuotes && content[i + 1] === '"') {
        current += content[++i];
      } else {
        inQuotes = !inQuotes;
      }
    } else if (!inQuotes && (char === "\n" || char === "\r")) {
      if (current.trim()) records.push(current);
      current = "";
      if (char === "\r" && content[i + 1] === "\n") i++;
    } else {
      current += char;
    }
  }
  if (current.trim()) records.push(current);
  if (inQuotes) throw new Error("Unterminated quoted CSV field");
  return records;
}

export function parseStylesCSV(csvContent: string): StyleData[] {
  const lines = splitCSVRecords(csvContent);
  if (lines.length < 2) return [];

  const headers = parseCSVLine(lines[0]);
  const column = new Map(headers.map((header, index) => [header, index]));
  const value = (fields: string[], header: string): string => {
    const index = column.get(header);
    return index === undefined ? "" : fields[index] || "";
  };

  const dataLines = lines.slice(1);
  return dataLines.map((line) => {
    const f = parseCSVLine(line);
    const primaryColors = value(f, "Primary Colors");

View on GitHub (pinned to a38d04c3d5)

Solutions

  1. Open the gallery's styles.csv, go to the last record the parser reached, and fix the unbalanced quote — remember quoted fields may span multiple lines.
  2. Ensure every quote character inside a quoted field is doubled (escaped as two quotes).
  3. Regenerate the CSV from the source of truth (src/ui-ux-pro-max/data/styles.csv via `npm run sync:assets`) instead of editing the gallery copy.
  4. If generating programmatically, use a proper CSV writer library rather than string concatenation.

Example fix

# before (broken csv - closing quote lost, inner quote not doubled)
5,"Neubrutalism,bold "outlines" ...
# after (inner quotes doubled, field terminated)
5,"Neubrutalism,bold ""outlines"" ..."
Defensive patterns

Strategy: validation

Validate before calling

function csvQuotesBalanced(content: string): boolean {
  let inQuotes = false;
  for (let i = 0; i < content.length; i++) {
    if (content[i] === '"') {
      if (inQuotes && content[i + 1] === '"') i++; // escaped quote
      else inQuotes = !inQuotes;
    }
  }
  return !inQuotes;
}

if (!csvQuotesBalanced(stylesCsv)) {
  throw new Error('styles.csv has an unterminated quoted field - fix the source CSV');
}

Try / catch

try {
  const styles = parseStylesCSV(csv);
} catch (e) {
  if (e instanceof Error && e.message.includes('Unterminated quoted CSV field')) {
    console.error('Malformed styles.csv - likely a lost closing quote; validate with a CSV linter');
  }
  throw e;
}

Prevention

When it happens

Trigger: Feeding parseStylesCSV() a styles.csv where a quoted multi-line field (descriptions with embedded newlines) lost its closing quote, a file truncated mid-field by a partial git checkout or bad copy, or programmatic CSV generation that doesn't escape/double inner quotes correctly.

Common situations: Hand-editing styles.csv and deleting a closing quote; CSV writers that emit raw quotes inside fields without doubling them; files edited with tools that strip or smarten quotes; line-ending rewrites breaking the parser's CRLF handling.

Related errors


AI-assisted analysis of nextlevelbuilder/ui-ux-pro-max-skill@a38d04c3d5 (2026-08-14). Data as JSON: /api/errors/130b83d73f8a12c1. Report an issue: GitHub.