Skip to content

fix(format): write BOM when only headers are emitted for empty input#1242

Open
abhu85 wants to merge 1 commit into
C2FO:mainfrom
abhu85:fix/write-bom-headers-only
Open

fix(format): write BOM when only headers are emitted for empty input#1242
abhu85 wants to merge 1 commit into
C2FO:mainfrom
abhu85:fix/write-bom-headers-only

Conversation

@abhu85

@abhu85 abhu85 commented Jun 22, 2026

Copy link
Copy Markdown

Problem

Fixes #1148.

When the input rows array is empty, writeBOM: true is ignored even though headers are still written via alwaysWriteHeaders:

writeToString([], { headers: ['a', 'b'], alwaysWriteHeaders: true, writeBOM: true });
// => "a,b"   (expected: "" + "a,b")

Cause

CsvFormatterStream pushes the BOM only in _transform:

public _transform(row, encoding, cb) {
    if (!this.hasWrittenBOM) { this.push(this.formatterOptions.BOM); this.hasWrittenBOM = true; }
    ...
}

_transform runs once per row, so with an empty input it never fires. The headers are flushed later in _flush (via rowFormatter.finish() under alwaysWriteHeaders), which had no BOM handling — so the headers come out with no BOM.

Fix

Write the BOM in _flush as well, guarded by hasWrittenBOM and only when finish actually produces content:

if (rows && rows.length > 0) {
    if (!this.hasWrittenBOM) { this.push(this.formatterOptions.BOM); this.hasWrittenBOM = true; }
    rows.forEach((r) => this.push(Buffer.from(r, 'utf8')));
}

The rows.length > 0 guard keeps truly-empty output (no rows, no headers) from emitting a lone BOM, and hasWrittenBOM prevents a double BOM when rows were present.

Test plan

  • Added a CsvFormatterStream test: formatRows([], { headers: ['a','b'], alwaysWriteHeaders: true, writeBOM: true }) resolves to ['', 'a,b'].
  • New test fails on main and passes with the fix.
  • jest packages/format231 passing; eslint --max-warnings 0 + prettier --check clean.

The BOM was pushed only in `_transform`, which never runs when the input
rows array is empty. With `writeBOM: true` and `alwaysWriteHeaders: true`
the headers are flushed in `_flush` with no preceding `_transform`, so no
BOM was written. Write the BOM in `_flush` too, when `finish` actually
produces content.
@c2fo-cibot c2fo-cibot Bot added the size/S Denotes a PR that changes 10-29 lines label Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/S Denotes a PR that changes 10-29 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] BOM is not written when writeToBuffer()'s first argument is an empty array

1 participant