{"record":{"id":"e16983677976f366","repo":"Budibase/budibase","slug":"could-not-read-csv","errorCode":null,"errorMessage":"Could not read CSV","messagePattern":"Could not read CSV","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/server/src/integrations/s3.ts","lineNumber":274,"sourceCode":"      throw new Error(\"Unable to retrieve CSV - invalid stream\")\n    }\n\n    let csvError = false\n    return new Promise((resolve, reject) => {\n      fileStream.on(\"error\", (err: Error) => {\n        reject(err)\n      })\n      const response = csv()\n        .fromStream(fileStream)\n        .on(\"error\", () => {\n          csvError = true\n        })\n      fileStream.on(\"end\", () => {\n        resolve(response)\n      })\n    }).catch(err => {\n      if (csvError) {\n        throw new Error(\"Could not read CSV\")\n      } else {\n        throw err\n      }\n    })\n  }\n\n  async delete(query: { bucket: string; delete: string }) {\n    return await this.client.deleteObjects({\n      Bucket: query.bucket,\n      Delete: JSON.parse(query.delete),\n    })\n  }\n}\n\nexport default {\n  schema: SCHEMA,\n  integration: S3Integration,\n}","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/integrations/s3.ts#L256-L292","documentation":"During CSV streaming, readCsv sets csvError=true when the stream emits an error event (a malformed/invalid CSV row) and the promise's catch converts that into 'Could not read CSV' to hide the low-level parser error. It signals the CSV content itself could not be parsed, as opposed to transport failures which are rethrown unchanged.","triggerScenarios":"The fileStream emits an 'error' event while piping rows (csvError flag set) — i.e. the parser rejects the CSV content mid-stream during an S3 read CSV query execution.","commonSituations":"Downloading a CSV with inconsistent column counts, wrong delimiter/quote characters, non-UTF8 encoding, or an HTML/JSON error page saved as .csv; truncated uploads; exporting tool produced malformed quoting that the CSV parser rejects.","solutions":["Open the S3 object and validate the CSV: check headers, quoting, delimiter, and that it is not an HTML/JSON error page — re-export the file correctly.","Re-upload the file ensuring UTF-8 encoding and consistent quoting (e.g. export with standard CSV tooling).","If the delimiter is non-comma, configure the query's CSV parsing options accordingly.","Check the object is fully uploaded and not truncated (compare sizes/checksums)."],"exampleFix":"// before: CSV with inconsistent columns / stray quotes\nname,age\n\"Alice,30\nBob,not,a,number\n// after: well-formed CSV re-exported\nname,age\nAlice,30\nBob,42\n","handlingStrategy":"try-catch","validationCode":"// Pre-validate the object parses before ingesting\nconst lines = csvText.split(\"\\n\")\nconst cols = lines[0].split(\",\").length\nif (lines.some(l => l.trim() && l.split(\",\").length !== cols)) {\n  throw new Error(\"Malformed CSV: inconsistent column counts\")\n}","typeGuard":"function isCsvParseFailure(err: unknown): err is Error {\n  return err instanceof Error && err.message === \"Could not read CSV\"\n}","tryCatchPattern":"try {\n  const csv = await s3Integration.readCsv(query)\n} catch (err) {\n  if (err instanceof Error && err.message === \"Could not read CSV\") {\n    // re-export/repair the source file, then retry\n  } else { throw err }\n}","preventionTips":["Export CSVs with standard tooling and UTF-8 encoding","Match the query's delimiter/quote settings to the actual file format","Checksum-compare uploads to catch truncated files","Open the object and confirm it is CSV, not an HTML/JSON error page"],"tags":["csv","s3","parsing","stream"],"backgroundTag":"csv-parse-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}