Formulas that fail without erroring
Why does {entity.internalid} not work in a NetSuite saved search formula?
Short answer
Because the token is {entity.id}. In a formula, internalid is not a resolvable name, and the failure is silent: the column fills with the literal string ERROR: Field Not Found on every row and the search reports success. One join level works with .id; two levels did not resolve in this run.
Because the token is {entity.id}. Inside a formula, internalid is not a name the engine resolves, and it fails the quiet way: the column comes back populated on every row with the literal string ERROR: Field Not Found, and the search reports success.
The cruelty is that internalid is what the field is called elsewhere in NetSuite, including in the Results column picker right next to the formula box you typed it into.
What resolves and what does not
Eight tokens were run as Formula(Text) Results columns on a transaction search, one call each:
{entity.internalid} -> ERROR: Field Not Found
{entity.id} -> an integer, the internal id <- works
{entity} -> a human-readable entity label <- works
{entity.entityid} -> ERROR: Field Not Found
{entity.parent.internalid} -> ERROR: Field Not Found
{entity.parent.parent.internalid} -> ERROR: Field Not Found
{entity.zzznosuchfield} -> ERROR: Field Not Found (control, bad leaf)
{zzznosuchrootfield} -> ERROR: Field Not Found (control, bad root)
Not one of the eight raised an error. All eight ran to completion and returned rows. Six of them returned a fabricated value while reporting success, which is covered in full on the page about that string.
The fix
Write {entity.id} for the internal id and {entity} for the label. One join level works, with .id.
Formula(Text) = {entity.id}
{entity.entityid} is the other natural guess, and it does not resolve either. Of the one-level spellings tried, only {entity.id} and bare {entity} came back with a value.
What the run cannot tell you about depth
Two levels did not work. {entity.parent.internalid} returned the string, and so did three levels. It is tempting to read that as a join depth limit, and this run cannot support that reading.
Here is why. The two deliberate-typo controls, a bad leaf on a valid join and a bad root field, returned the identical string. So the string does not mean "you have exceeded the join depth" or "this join is unsupported". It means "I could not resolve this name", and it is emitted the same way for a plausible-but-wrong path as for a nonsense one. From the output alone you cannot tell the two apart.
Which means the honest statement is: {entity.parent.internalid} does not work, and the reason it does not work was not established. It could be depth, or it could be internalid failing again one level further in. That distinction was not tested, and guessing it would tell you nothing you could act on anyway, because the fix in both cases is to stop writing internalid and see what happens.
How to tell if you are affected
Grep your saved searches for internalid inside braces. In a Criteria filter, plain internalid without braces is an ordinary field rather than a formula token. In a formula, with braces and after a dot, it is the failing spelling.
Then export any report that carries a formula column and search the file for ERROR. The string is exact and 22 characters, and a working formula column never contains it. A report that has been running for a year with a dead join looks exactly like a report that works, until you look at that column.
Scope: one sandbox account on NetSuite 2026.1, Administrator role, eight token variants on a single record type. These searches were built and run ad hoc through the SuiteScript search engine (nlapiCreateSearch / runSearch) without saving anything. Only the entity join was tested, so treat the working spelling as .id in general and the depth behaviour as untested beyond that one path.
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 my saved search formula column say "ERROR: Field Not Found" instead of a value?
Because the search succeeded. A field token in a Results formula did not resolve, and NetSuite writes the literal 22-character string "ERROR: Field Not Found" into the column as its value on every row. It is data, not an exception, it appears in Formula(Numeric) columns, it survives SUM, and NVL does not protect it.
- Why does {type} return "Opportunity" but {type.id} returns "Opprtnty"?
Because {field} gives the display name and {field.id} gives the internal code. They are two different strings for the same value. {field.name} does not exist and fails silently. Note the trap: SuiteQL returns the code by default where a saved search formula returns the label, so literals copied between the two engines match nothing.
- Why is equalto not a valid operator on internalid in a saved search filter?
Because NetSuite does not accept equalto on internalid: the filter is refused with SSS_INVALID_SRCH_OPERATOR and the search returns an error instead of rows. Use anyof, which takes an array and scales to a list. is also works, on a bare string, which is the part most people do not expect.
From the blog
- NetSuite Field Explorer vs MokuBot: Two Different Questions
Field Explorer tells you what a field is called. MokuBot uses the field. An honest comparison of the two, including where Field Explorer is still the better tool.