{"record":{"id":"e765b9643614d274","repo":"linshenkx/prompt-optimizer","slug":"variables-importer-errors-csvminrows","errorCode":null,"errorMessage":"variables.importer.errors.csvMinRows","messagePattern":"variables\\.importer\\.errors\\.csvMinRows","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/components/variable/VariableImporter.vue","lineNumber":252,"sourceCode":"    csv: t('variables.importer.csvTextHelp'),\n    txt: t('variables.importer.txtTextHelp')\n  }\n  return helps[textFormat.value] || helps.csv\n}\n\nconst parseVariables = (data: unknown, format: 'csv' | 'txt' = 'csv'): Record<string, string> => {\n  if (format === 'csv') {\n    return parseCsvVariables(data as string)\n  } else if (format === 'txt') {\n    return parseTxtVariables(data as string)\n  }\n  throw new Error(t('variables.importer.errors.unsupportedFormat'))\n}\n\nconst parseCsvVariables = (content: string): Record<string, string> => {\n  const lines = content.trim().split('\\n')\n  if (lines.length < 2) {\n    throw new Error(t('variables.importer.errors.csvMinRows'))\n  }\n  \n  const headers = lines[0].split(',').map(h => h.trim().replace(/\"/g, ''))\n  const nameIndex = headers.findIndex(h => ['name', 'key', 'variable'].includes(h.toLowerCase()))\n  const valueIndex = headers.findIndex(h => ['value', 'val'].includes(h.toLowerCase()))\n  \n  if (nameIndex === -1 || valueIndex === -1) {\n    throw new Error(t('variables.importer.errors.csvRequiredColumns'))\n  }\n  \n  const variables: Record<string, string> = {}\n  \n  for (let i = 1; i < lines.length; i++) {\n    const cells = lines[i].split(',').map(c => c.trim().replace(/\"/g, ''))\n    if (cells.length > Math.max(nameIndex, valueIndex)) {\n      const name = cells[nameIndex]\n      const value = cells[valueIndex]\n      if (name && value !== undefined) {","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/components/variable/VariableImporter.vue#L234-L270","documentation":"parseCsvVariables splits the trimmed CSV content on newlines and requires at least 2 lines: one header row plus at least one data row. Fewer than 2 lines (empty file or header-only file) throws this error before any column parsing occurs.","triggerScenarios":"Importing an empty CSV (content.trim() === ''), a CSV containing only a header line like 'name,value', or a file whose line endings produce a single line after trimming.","commonSituations":"User exports an empty template, downloads a header-only CSV, or the file read returned '' (wrong file handle, upload truncated). Files with only CR (\\r) line endings also split into one 'line' since split is on '\\n'.","solutions":["Ensure the CSV has a header row (name/key/variable and value/val) plus at least one data row.","Check the file content before import: if (content.trim().length === 0) reject early with a friendlier message.","If CRLF/CR-only files are expected, normalize line endings: content.replace(/\\r\\n?/g, '\\n') before splitting."],"exampleFix":"// before\nconst lines = content.trim().split('\\n')\n// after\nconst lines = content.trim().replace(/\\r\\n?/g, '\\n').split('\\n').filter(l => l.trim().length > 0)","handlingStrategy":"validation","validationCode":"const text = (await file.text()).replace(/^\\uFEFF/, '').replace(/\\r\\n?/g, '\\n').trim()\nconst dataRows = text.split('\\n').filter(l => l.trim().length > 0)\nif (dataRows.length < 2) {\n  showError('CSV must contain a header row and at least one data row')\n  return\n}","typeGuard":"const hasCsvDataRows = (content: string): boolean =>\n  content.trim().replace(/\\r\\n?/g, '\\n').split('\\n').filter(l => l.trim()).length >= 2","tryCatchPattern":"try { parseCsvVariables(content) } catch (e) { if (e instanceof Error && e.message.includes('csvMinRows')) { /* tell user the file is empty or header-only */ } else throw e }","preventionTips":["Trim and normalize line endings before parsing.","Filter out blank lines so trailing newlines don't inflate the row count.","Validate file size > 0 before attempting import."],"tags":["csv","file-import","validation","parsing"],"backgroundTag":"empty-or-header-only-csv","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}