Reporting on NetSuite custom fields: why they disappear
Why NetSuite custom fields disappear from reports: store value, applies-to, field type and role access, plus how to query custbody and custcol fields.
A NetSuite custom field is missing from your report for one of four reasons: Store Value is off, so nothing is stored to search on; the field isn't applied to the record type you're searching; the type isn't searchable as you assume; or your role can't see it. Saved searches and SuiteQL see every stored custom field; the Report Builder often does not.
Key takeaways
- If Store Value is off, the field has no value in the database. It can be displayed and it cannot be reported on. This is the single most common cause of a 'missing' custom field.
- The Applies To settings decide which record types carry the field. A transaction body field not applied to Invoice will never appear in an invoice search, however visible it looks on a sales order.
- Custom field internal ids tell you where the field lives: custbody on transaction headers, custcol on transaction lines, custentity on entities, custitem on items, custrecord on custom records.
- Multiple-select fields store a delimited list of internal ids. They cannot be joined, which makes them the worst choice for any dimension you intend to report by.
- A sourced field with Store Value on is a snapshot taken when the record was saved. It does not update when the source record changes, and that is usually a feature, not a bug.
The complaint arrives the same way every time. Someone added a custom field to a NetSuite record eighteen months ago, everyone has been filling it in diligently since, and now that it matters for reporting it isn't in the field list. Or worse: it is in the field list, the search runs, and every row comes back blank. NetSuite custom field reporting fails in a small number of specific ways, and each one has a tell.
Six reasons the field isn't in your report
Check these in order. The first two account for most cases and both take under a minute to confirm on the custom field record itself.
- 1.Store Value is unchecked. With Store Value off, NetSuite computes or sources the value for display and never writes it to the database. There is nothing to search on, nothing to export, nothing in SuiteQL. The field looks completely normal on screen, which is what makes this so frustrating to diagnose.
- 2.The field isn't applied to the record type you're searching. The Applies To settings on a custom field control which record types get it. A transaction body field applied to Sales Order and Item Fulfilment but not Invoice is invisible in an invoice search, even though users see it on the order they're looking at.
- 3.You're in the Report Builder, not a saved search. The Report Builder works from a curated field list for each report type, and plenty of custom fields simply aren't offered in it. Saved searches and SuiteQL can see anything that is stored. "It's not in the report" is usually a report limitation rather than a data problem.
- 4.Your role can't see it. Custom fields can be restricted by role, with view or edit access set per role. If the field is restricted and your role isn't on the list, it won't appear in your search field list at all — and it will appear for the administrator who tells you the field is fine.
- 5.The field type isn't stored the way you expect. Inline HTML has no stored value by design. Rich Text stores markup, so exports arrive with tags in them. Long Text doesn't behave like Free-Form Text in grouping and formulas. See the table below.
- 6.There are two fields with the same label. Labels aren't unique; internal ids are. Two fields called "Region" on the same record, created by two different people two years apart, with 40% of records populated in one and 60% in the other, is a real and common finding. The internal id is the only thing to trust.
Field type decides what reporting is possible
Choose the field type for how the data will be reported, not for how the form should look. This is the decision that either saves or costs you a day, two years later.
| Field type | What's stored | Reporting behaviour |
|---|---|---|
| Free-Form Text | The string | Groups, filters and sorts cleanly. The safe default for anything short. |
| Text Area / Long Text | Longer strings | Fine for display and keyword filters. Awkward to group by and limited in formulas — don't use it as a dimension. |
| Rich Text | Markup as well as text | Exports carry HTML tags. Never use it for anything you will group, compare or dedupe. |
| List/Record | The internal id of the selected record | The best choice for a dimension. Searches show the label; SuiteQL returns the id, so wrap it in BUILTIN.DF() to get the text. |
| Multiple Select | A delimited list of internal ids | Cannot be joined. Reportable only with string matching. Avoid for anything you'll slice by. |
| Check Box | T or F | Perfectly behaved. Reports as a two-value dimension, and formulas can count it directly. |
| Date / Datetime | A date value | Filters and period grouping work as expected. Datetime carries a time component that will surprise a day-boundary filter. |
| Currency / Decimal / Integer | A number | Sums and averages properly. Currency fields follow the record's currency, so mixed-currency totals need converting first. |
| Percent | A number with percent display | Check whether 15% is stored as 15 or 0.15 in your account before you multiply anything by it. |
| Inline HTML | Nothing | Display only. It will never appear in a search, a report or an export. |
Body fields, line fields, and the double-count
Transactions have two kinds of custom field and mixing them up produces numbers that are wrong rather than missing. A body field lives once on the header. A column field lives on every line. Put a body field into a line-level search and its value repeats on every line — so if that body field happens to be a currency amount and someone sums it, a five-line invoice reports five times the real figure.
- Reporting a body field on its own? Filter Main Line to true so you get one row per transaction.
- Reporting a body field alongside line detail? Keep it as a grouping or a maximum in the summary, never a sum.
- Reporting a line field? Main Line false, and exclude tax and shipping lines, or your line count will include rows a user never typed.
Custom field ids are long and queries that use them get unreadable fast. Paste one in to get clause breaks and consistent keyword casing back.
Reading a custom field id
The prefix on an internal id tells you where the field lives, which tells you which table it will appear on in SuiteQL. This is the fastest orientation trick in NetSuite reporting.
| Prefix | Where the field lives | Where it appears in SuiteQL |
|---|---|---|
custbody_ | Transaction body (header) | A column on transaction |
custcol_ | Transaction line / column | A column on transactionline |
custentity_ | Entity records: customer, vendor, employee, contact, partner | A column on customer, vendor and the other entity tables |
custitem_ | Item records | A column on item |
custrecord_ | Fields on custom records, and fields on other record types | A column on the customrecord_* table that owns it |
custevent_ | CRM records such as events and cases | A column on the relevant CRM table |
In a query, stored custom fields are just columns. There is no special syntax and no join required:
SELECT
t.tranid,
t.trandate,
t.custbody_project_code AS project_code,
BUILTIN.DF(t.custbody_delivery_region) AS delivery_region,
tl.custcol_line_reference AS line_reference,
ABS(tl.netamount) AS line_amount
FROM transaction t
JOIN transactionline tl
ON tl.transaction = t.id
WHERE t.type = 'CustInvc'
AND t.posting = 'T'
AND tl.mainline = 'F'
AND tl.taxline = 'F'
ORDER BY t.trandate DESCMultiple-select fields, and why to avoid them
A Multiple Select field stores several internal ids in one delimited string. You cannot join it to the referenced table, so every reporting approach is a workaround. String matching works if you pad the boundaries — without the padding, id 12 matches ids 120, 121 and 512:
-- Fragile but sometimes the only option
SELECT t.tranid, t.custbody_service_tags
FROM transaction t
WHERE ',' || t.custbody_service_tags || ',' LIKE '%,12,%'If a dimension needs to be many-valued and you need to report by it, the right structure is a child custom record — one row per record-and-value pair — which you can join like anything else. That turns an unqueryable string into a proper relation. How to query NetSuite custom records covers the naming and discovery side, and SuiteQL join examples has the join patterns.
Sourced fields are snapshots, not links
A custom field can source its value from a related record — pulling a customer's region onto every invoice, for instance. The behaviour depends entirely on Store Value. With it off, the field displays the current value from the source and reports as empty. With it on, the value is written when the record is saved and then frozen.
That freezing is usually what you want in finance. If a customer moves from the North region to the South in March, last year's invoices should still report under North, because that's where the revenue was earned. But it does mean a field that looks like a live lookup isn't one, and re-saving a batch of old records will silently rewrite history. Decide which behaviour you want, write it down on the field's description, and stop rediscovering it every audit.
Before you add another custom field
- Is there a standard field that does this? Class, department, location and the item hierarchy are already joined to everything and already in every report. A custom field duplicating one of them creates two versions of the truth.
- Is it a dimension or a note? Dimensions are List/Record with a maintained list behind them. Notes are text. A free-text field used as a dimension gives you "North", "north", "Nrth" and "North " as four regions.
- Who is allowed to leave it blank? Set it mandatory at creation or accept permanent gaps. Retrofitting completeness onto 60,000 historical records is a CSV update project, not a report fix.
- Will it end up in a spreadsheet? Most custom-field reporting ends as an export someone reshapes. Search results move around as CSV and JSON more than anyone admits, and the CSV to JSON converter and JSON to CSV converter save the fiddly quoting step in the middle.
- Are you about to hit a search ceiling? Custom-field reporting is where saved searches usually run out of room, because the interesting questions need formula columns over joined fields. NetSuite saved search limitations sets out where the actual limits are.
The shortcut
Diagnosing a missing custom field means checking Store Value, checking Applies To, checking role access, then working out which table the id lives on. It is entirely learnable and it is also the reason simple questions about your own data take an afternoon. builds a dictionary of your account's real fields — including the custom ones, with their types and where they're stored — so asking "revenue by delivery region for Q2" resolves to your custbody_delivery_region field, computed live, with the SuiteQL shown so you can see exactly which field it used and whether that was the one you meant.
Frequently asked questions
Why is my NetSuite custom field not showing in a saved search?
Most often because Store Value is unchecked on the field, so no value exists in the database to search. The next most likely causes are that the field isn't applied to the record type you're searching, or that role-level access on the field excludes your role. All three are visible on the custom field record itself.
What does Store Value do on a NetSuite custom field?
It controls whether the value is written to the database. With Store Value on, the value is saved with the record and can be searched, exported and queried. With it off, NetSuite only computes or sources the value for display, so the field appears normal on screen but is invisible to every reporting tool.
How do I query a NetSuite custom field in SuiteQL?
Stored custom fields are ordinary columns. Transaction header fields appear as custbody_ columns on the transaction table, line fields as custcol_ columns on transactionline, entity fields as custentity_ columns on customer or vendor, and item fields as custitem_ columns on item. Wrap List/Record fields in BUILTIN.DF() to get the label instead of the internal id.
Which NetSuite custom field types can be reported on?
Free-Form Text, List/Record, Check Box, Date, Currency, Decimal, Integer and Percent all report cleanly. Long Text and Text Area work for display and keyword filters but are awkward as grouping dimensions. Multiple Select stores a delimited id list and can't be joined. Inline HTML stores nothing at all and never appears in reports.
Why do my custom field values repeat on every line of a transaction search?
Because it is a transaction body field, which lives once on the header and is echoed onto every line of a line-level search. Filter Main Line to true if you want one row per transaction, and never sum a body field in a line-level result — a five-line invoice will report the value five times.
Do custom fields appear in NetSuite's standard reports?
Sometimes. The Report Builder works from a curated field list per report type and many custom fields aren't offered there, even when the data is stored and perfectly searchable. If a field is visible in a saved search but not in the report you're customising, that's a report limitation — build the saved search instead.
Calculators for this
Format SuiteQL and SQL in your browser: keyword casing, clause line breaks, indented joins and subqueries, plus a one-line minify mode.
Convert CSV to a JSON array of objects in your browser. Quoted fields, any delimiter, optional header row, type coercion, and ragged-row warnings.
Convert a JSON array to CSV in your browser. Column union across every object, dot-notation flattening, correct quote escaping, delimiter choice.
Keep reading
Query NetSuite custom records with SuiteQL: find the customrecord_ table name, discover custrecord_ fields, and join to customers and transactions.
The real ceilings of NetSuite saved searches: join depth, summary maths, row limits and performance, plus the right tool to use for each one.
Worked SuiteQL join examples: transaction to transactionline to customer, item and custom record joins, plus when left joins change the answer.
Build a top customers by revenue report in NetSuite, and see why revenue, invoiced and collected give three different rankings of the same customers.