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
- 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.
- Ensure every quote character inside a quoted field is doubled (escaped as two quotes).
- 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.
- 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
- Lint CSVs in CI (balanced quotes, header contract) before the gallery build.
- Generate CSVs with a real writer library that escapes inner quotes by doubling them.
- Never hand-edit the generated copy; edit the source of truth and re-run sync:assets.
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
- Unknown or missing style status: ${status || "<empty>"}
- invalid hex color '{value}'
- Unknown AI type: ${aiType}
- Invalid JSON file {path}: {error}
- Invalid relevance fixture:\n- {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.