Your SuiteScript Runs in a Context You Didn't Choose
The script works when you click the button — it breaks when the integration does the same thing.

Your SuiteScript Runs in a Context You Didn't Choose
The script works when you click the button.
It breaks when the integration does the same thing.
The Problem Nobody Talks About Early Enough
SuiteScript has an execution context. Every time your code runs, NetSuite knows how that execution was triggered — whether a user clicked Save, a scheduled job fired, a CSV import processed a row, a RESTlet received a request, or a SOAP call hit the record.
This isn't just metadata. It changes behavior.
It changes which scripts fire. It changes who the "current user" is. It changes governance limits. It changes whether your beforeSubmit runs the way you think it does — or whether your own context checks quietly skip the path that matters.
Most SuiteScript developers learn this the hard way. A user event script gets written, tested manually, deployed, and forgotten. Three weeks later, an integration team starts pushing records via SOAP or REST, and the script either breaks, silently skips, or does something nobody expected.
The execution context wasn't part of the test plan because nobody asked: "What else touches this record?"
Contexts Are Not Interchangeable
Here's a partial list of what changes between contexts:
Client scripts don't fire on server-side record creation. SOAP, RESTlets, scheduled scripts, CSV imports — none of them trigger client-side validation. If your only validation lives in a client script, it's not validation. It's a suggestion.
CSV import has its own execution context. User event scripts fire, but
runtime.executionContextreturnsCSV_IMPORT. Sublist handling, field sourcing, and default values can behave differently from interactive saves. I've seen abeforeSubmitthat set a required custom field based on the subsidiary — worked perfectly in the UI, threw on every CSV row because the sourcing order was different and the dependency field wasn't populated yet when the logic ran.Scheduled scripts run under their own execution context, but the deployment role still matters. Permissions, subsidiaries, and role-based branches can change the result even when the code didn't change. If your code calls
runtime.getCurrentUser()and branches based on role, you need to know what role that deployment is configured to run as — and what happens when someone changes it.Web services (SOAP/REST) skip client scripts entirely. They trigger user event scripts, but
runtime.executionContextreturnsWEBSERVICESinstead ofUSERINTERFACE. If yourbeforeSubmitchecksruntime.executionContext === runtime.ContextType.USERINTERFACEand only runs validation inside that branch, every integration-created record bypasses it. I've audited environments where sales orders created via SOAP had been shipping without the margin validation that the UI enforced — for months.Workflow action scripts run in yet another context. Governance limits apply differently. If both a workflow and a user event script modify the same field, execution order determines who wins — and that order isn't always obvious.
The Pattern
- Developer writes a user event script.
- Tests it in the UI.
- Deploys it.
- Months later, a new integration starts creating the same record type.
- Something breaks — or worse, something silently doesn't happen.
Common casualties:
- Field defaults that rely on client-side
pageInitlogic. The integration never triggerspageInit, so the field is empty. - Role-based branching that assumes an interactive user. The integration runs as a generic API user with a different role — or a role that doesn't match any of your branches.
- Governance limits that were fine for single-record UI saves but blow up under bulk scheduled processing.
- Error handling that calls
dialog.alert()— which doesn't exist outside a client script context.
What to Do Instead
Start every script with one question: "What execution contexts will this code run in?"
Then build accordingly:
Check context explicitly. Use
runtime.executionContextto branch behavior when the context genuinely matters. Don't use it to paper over bugs — use it to handle legitimate differences in how the record arrives.Don't rely on client scripts for data integrity. Client scripts are UX. If a value must be validated before save, that validation belongs in
beforeSubmit.Test with the actual integration path. If records come in via SOAP, test via SOAP. If they come in via CSV, test via CSV. UI testing is not sufficient when the production path is something else.
Document the deployment user. For scheduled scripts, know who the script runs as. Review what happens if that user's role changes, their account is deactivated, or someone swaps the deployment configuration.
Audit existing scripts for context assumptions. Look for
getCurrentUser(),dialog,currentRecord, and any logic that only makes sense in an interactive context. If those scripts are deployed on record types that integrations touch, you have a latent bug.
Bottom Line
SuiteScript execution context isn't an advanced topic. It's a foundational one.
These bugs are rarely hard to fix.
They're hard to find because the UI test passes.
Your script has to care about context before production teaches it to.
Written by the team at Adaptive Solutions Group — NetSuite consultants based in Pittsburgh, PA.