Results, export and sharing
Why does my saved search CSV export have two columns with the same header?
Short answer
NetSuite writes the column label straight into the CSV header with no disambiguating suffix, so selecting the same field twice gives you the same header twice. The fix is custom column labels: they are honoured exactly as typed, in both detail and summary exports.
Because the header line is just the column labels, written out in order, with nothing added to make them unique. Select the same field twice, or two fields that happen to share a label, and the CSV header carries that label twice.
What it looks like
The detail export tested came out with Internal ID in the header twice:
Internal ID,Internal ID,Date,probe_bucket
Both of those columns carried identical values on every row of the file, checked across the whole export with zero mismatches. So this was a genuine duplicate of one field rather than two different fields that happen to share a display name. Either case produces the same header, which is the point: the file gives you no way to tell them apart.
Why it matters more than it looks
A human reading the file shrugs. Anything that loads it into a keyed structure does not:
- A
dictper row keeps the last value and drops the first, silently. - A dataframe requiring unique column names either errors or renames one column with a suffix of its own invention, which then differs between tools.
- A CSV import into a database fails on the duplicate target column, or maps both source columns onto one.
The failure mode that costs the most is the silent one, because the import succeeds, the row counts look right, and one column of the data quietly is not the column anyone thinks it is.
The fix
Give the columns distinct labels in the saved search itself. A custom label set on a results column is honoured exactly as typed, and the header collision disappears with it.
That part was tested directly and it works cleanly. Every custom label survived into the CSV header character for character, in both a detail export and a summary export, and labels are not silently replaced by field names anywhere in either file. If you name your columns, you get your names.
This is worth doing as policy rather than as a repair. Any saved search that feeds an integration should have every results column labelled explicitly, because then the header line is something you wrote and can rely on, instead of something NetSuite assembled out of whatever the field labels happen to be at export time.
Two things about the summary export that go with this, since they affect the same consumers. The grouped export contains its group rows and the Total row, so the total is a row in the file and not a separate footer. That total row does not format like the rows above it, which is a separate trap covered in why the Total row does not parse as a number.
How to tell if you are affected
Read the first line of the export, not the spreadsheet view of it:
head -1 export.csv | tr ',' '\n' | sort | uniq -d
Anything that prints is a duplicated header, and any consumer of that file is currently resolving the collision on its own terms without telling you. Fix it at the source, in the saved search, rather than in the parser, so that every consumer of that file gets the same fix.
Scope: one sandbox account on NetSuite 2026.1, Administrator role, two exports taken through the Export - CSV button on the results page, one detail and one summary. The duplicate header appeared in the detail export. Custom labels were verified in both.
How this was established
1 probe run against one NetSuite 2026.1 sandbox account on the Administrator role, through the saved search UI and the SuiteScript search engine. Where this page draws a boundary around a finding, that boundary is the edge of what was actually run.
Related
- Why does the Total row of my saved search CSV export fail to parse as a number?
The Total row formats that column differently from the rows above it, adding a thousands separator and a trailing .0, which forces CSV quoting. A parser gets integers for the body and a string for the total, so a cast returns NaN or a value silently truncated at the separator, on the total row only, with no warning.
- Why does my saved search only show 500 rows in the browser?
The results page renders a fixed 500-row window and never says so. The size URL parameter is ignored, there is no truncation warning and no pagination control, and the correct Total sits at the bottom of a page showing a fraction of it. The CSV export from the same page is complete and matched that Total exactly.
- How do I count the number of rows a NetSuite saved search returns?
Add a Formula(Numeric) results column whose formula is the literal 1 and set its Summary to Sum. That total is the row count. Count does not give you one: it is COUNT(DISTINCT), so Count of {internalid} returns distinct transactions and Count of a constant returns 1.