You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
NetSuite - Tax import fails with a OAuth 2.0 #101409
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
Identify the pull request that introduced this issue and revert it.
Classification: Backend bug (root cause is outside the App repo — no App code change in this release touches the NetSuite tax-import path) Causing PR: None. No PR in Deploy Checklist: New Expensify 2026-09-16 modifies any NetSuite source file (High confidence that no App PR in this deploy is involved; Low confidence on the exact backend trigger) Related Issues: NetSuite - 2FA required to connect (Expensify/App#101408) — same tester, same account, same release, also NetSuite OAuth 2.0; R4: Make REST + OAuth 2.0 the default for new NetSuite connections (Expensify/App#96570) — the in-flight NetSuite SOAP→REST / OAuth 2.0 migration this behaviour belongs to
Recommendation: NEEDS INVESTIGATION
Every file in the tax-toggle code path is byte-identical between production and staging, and the App never produces an "OAuth 2.0" error string for this action — the message is server-supplied, so there is nothing here to revert or roll forward in App. This appears to be a backend/internal issue; a separate internal investigation is needed.
Labels: No changes. DeployBlockerCash is kept — the issue is not reproducible on production, DeployBlocker is not present (so removing DeployBlockerCash would leave the issue with no blocker label), and the backend trigger is not yet confirmed. Nothing was removed.
📋 Detailed Analysis
Evidence
The App cannot generate an "OAuth 2.0" message for this action. Toggling Tax runs exactly one code path:
The toggle in NetSuiteImportPage.tsx#L114-L131 calls updateNetSuiteSyncTaxConfiguration and renders getLatestErrorField(config, 'syncTax').
NetSuiteCommands.ts#L580-L588 is a plain API.write(UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION, {policyID, enabled}) — the request payload is two fields, so there is no way for the client to send malformed data here.
The client's own failure message is the generic one — NetSuiteCommands.ts#L224-L225 writes getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage') into errorFields.syncTax. Any specific text the tester saw, including anything naming OAuth 2.0, therefore came from the API response, not from App.
The only "OAuth 2.0" copy in App is unrelated to this flow. A full-tree search of staging finds a single match: the NetSuite setup-wizard step en.ts#L5731-L5733 ("Enable OAuth 2.0" / "In NetSuite, go to Setup > Company > Enable Features > SuiteCloud > under Manage Authentication, enable OAuth 2.0"). That string is only rendered inside the connect wizard, never on the Accounting > Import page.
Staging-only is explained by state, not code. This account sits behind the netSuiteOAuth beta (CONST/index.ts#L1110), which is part of the still-open NetSuite SOAP→REST + OAuth 2.0 migration tracked in R4: Make REST + OAuth 2.0 the default for new NetSuite connections. Betas and API responses differ between the staging and production backends with zero client-code difference. The sibling blocker NetSuite - 2FA required to connect was filed minutes earlier by the same tester on the same account and is the OAuth-2.0 connect flow behaving as designed — strongly suggesting this workspace's connection was established over OAuth 2.0 / REST, and that the failure is in the server-side tax import for that transport.
Only web platforms are checked on this report (Win 11 Chrome, macOS Chrome/Safari), so the mobile submodule bumps in this checklist cannot be involved either.
Verification
Affected code path and its production vs staging state:
I also pulled the complete production...staging raw diff (the compare API's file list is capped at 300 entries, so the file list alone is not trustworthy) and grepped it case-insensitively for netsuite, syncTax, suiteTax and oauth. The only NetSuite hits are three help-site markdown articles from [No QA] Add NS0995 help article for deactivated NetSuite employees plus incidental context lines. No NetSuite src/ file changed.
Candidate PRs checked and ruled out:
[Merge ATS] Generalize merge connection for ATS — closest match by area (it is the only PR touching src/libs/actions/connections/index.ts), but the diff only moves the Merge HR/ATS "initial sync modal shown" Onyx keys into connections/merge/. It does not touch NetSuite, sync options, or error fields.
Sort vendor pickers alphabetically — the src/libs/PolicyUtils.ts change in this release is entirely vendor sorting (getSageIntacctVendors, new sortVendors); canUseTaxNetSuite and settingsPendingAction are untouched.
Nothing in the App code shipped in 9.4.81-0 changed this flow. Toggling Tax sends a two-field UpdateNetSuiteSyncTaxConfiguration write and then displays whatever the API puts in errorFields.syncTax; the App's own fallback is the generic error string, so the OAuth 2.0 wording the tester saw originated server-side. The most likely explanation, consistent with NetSuite - 2FA required to connect landing at the same time on the same account, is that this workspace's connection runs on the new OAuth 2.0 / REST transport from the in-progress migration in R4: Make REST + OAuth 2.0 the default for new NetSuite connections, and the tax import for that transport (or the NetSuite account's OAuth 2.0 / REST Web Services feature configuration) is not yet working on staging.
Next steps, all outside the App diff:
Grab the requestID from the failing UpdateNetSuiteSyncTaxConfiguration request (visible in the video attachment / browser network tab) so the server-side error and its NetSuite error code can be read directly.
Confirm whether this workspace's NetSuite connection was created through the OAuth 2.0 wizard or the legacy token flow, and whether tax import is expected to work for the OAuth 2.0 / REST transport at this stage of the migration. If tax import is a known not-yet-shipped part of that migration, this is an expected beta gap rather than a release regression and can be demoted.
cc @yuwenmemon@akinwale — owners of the NetSuite OAuth 2.0 work, for context on (2). No blame implied: no PR in this checklist is involved.
@yuwenmemon this issue was created 2 weeks ago. Are we close to a solution? Let's make sure we're treating this as a top priority. Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!
This issue has not been updated in over 15 days. @yuwenmemon, @applausebot eroding to Monthly issue.
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!
Activity
applause-bot commentedon Sep 17, 2026
While Applause doesn't embed attachments for this bug, here are the links for quick view:
https://platform.applause.com/services/links/v1/external/292489865ed4722d16c363f7ec6b4299d8e180231e3571c0beb2d18c3428c287
github-actions commentedon Sep 17, 2026
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
melvin-bot commentedon Sep 17, 2026
Triggered auto assignment to @Valforte (
DeployBlockerCash), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.melvin-bot commentedon Sep 17, 2026
💬 A slack conversation has been started in #expensify-open-source
MelvinBot commentedon Sep 17, 2026
🔍 Investigation Summary
Classification: Backend bug (root cause is outside the App repo — no App code change in this release touches the NetSuite tax-import path)
Causing PR: None. No PR in Deploy Checklist: New Expensify 2026-09-16 modifies any NetSuite source file (High confidence that no App PR in this deploy is involved; Low confidence on the exact backend trigger)
Related Issues: NetSuite - 2FA required to connect (
Expensify/App#101408) — same tester, same account, same release, also NetSuite OAuth 2.0; R4: Make REST + OAuth 2.0 the default for new NetSuite connections (Expensify/App#96570) — the in-flight NetSuite SOAP→REST / OAuth 2.0 migration this behaviour belongs toRecommendation: NEEDS INVESTIGATION
Every file in the tax-toggle code path is byte-identical between
productionandstaging, and the App never produces an "OAuth 2.0" error string for this action — the message is server-supplied, so there is nothing here to revert or roll forward in App. This appears to be a backend/internal issue; a separate internal investigation is needed.Labels: No changes.
DeployBlockerCashis kept — the issue is not reproducible on production,DeployBlockeris not present (so removingDeployBlockerCashwould leave the issue with no blocker label), and the backend trigger is not yet confirmed. Nothing was removed.📋 Detailed Analysis
Evidence
The App cannot generate an "OAuth 2.0" message for this action. Toggling Tax runs exactly one code path:
NetSuiteImportPage.tsx#L114-L131callsupdateNetSuiteSyncTaxConfigurationand rendersgetLatestErrorField(config, 'syncTax').NetSuiteCommands.ts#L580-L588is a plainAPI.write(UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION, {policyID, enabled})— the request payload is two fields, so there is no way for the client to send malformed data here.NetSuiteCommands.ts#L224-L225writesgetMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')intoerrorFields.syncTax. Any specific text the tester saw, including anything naming OAuth 2.0, therefore came from the API response, not from App.The only "OAuth 2.0" copy in App is unrelated to this flow. A full-tree search of
stagingfinds a single match: the NetSuite setup-wizard stepen.ts#L5731-L5733("Enable OAuth 2.0" / "In NetSuite, go to Setup > Company > Enable Features > SuiteCloud > under Manage Authentication, enable OAuth 2.0"). That string is only rendered inside the connect wizard, never on the Accounting > Import page.Staging-only is explained by state, not code. This account sits behind the
netSuiteOAuthbeta (CONST/index.ts#L1110), which is part of the still-open NetSuite SOAP→REST + OAuth 2.0 migration tracked in R4: Make REST + OAuth 2.0 the default for new NetSuite connections. Betas and API responses differ between the staging and production backends with zero client-code difference. The sibling blocker NetSuite - 2FA required to connect was filed minutes earlier by the same tester on the same account and is the OAuth-2.0 connect flow behaving as designed — strongly suggesting this workspace's connection was established over OAuth 2.0 / REST, and that the failure is in the server-side tax import for that transport.Only web platforms are checked on this report (Win 11 Chrome, macOS Chrome/Safari), so the mobile submodule bumps in this checklist cannot be involved either.
Verification
Affected code path and its
productionvsstagingstate:productionblobstagingblobsrc/pages/workspace/accounting/netsuite/import/NetSuiteImportPage.tsxb3e5a1deb3e5a1desrc/libs/actions/connections/NetSuiteCommands.ts80922e7680922e76src/libs/ErrorUtils.tsI also pulled the complete
production...stagingraw diff (the compare API's file list is capped at 300 entries, so the file list alone is not trustworthy) and grepped it case-insensitively fornetsuite,syncTax,suiteTaxandoauth. The only NetSuite hits are three help-site markdown articles from [No QA] Add NS0995 help article for deactivated NetSuite employees plus incidental context lines. No NetSuitesrc/file changed.Candidate PRs checked and ruled out:
src/libs/actions/connections/index.ts), but the diff only moves the Merge HR/ATS "initial sync modal shown" Onyx keys intoconnections/merge/. It does not touch NetSuite, sync options, or error fields.src/libs/PolicyUtils.tschange in this release is entirely vendor sorting (getSageIntacctVendors, newsortVendors);canUseTaxNetSuiteandsettingsPendingActionare untouched.src/CONST/index.tsis removingEXPENSIFY_CARD_EU_UK;NETSUITE_USA_TAXandNETSUITE_OAUTHare unchanged.Root Cause
Nothing in the App code shipped in
9.4.81-0changed this flow. Toggling Tax sends a two-fieldUpdateNetSuiteSyncTaxConfigurationwrite and then displays whatever the API puts inerrorFields.syncTax; the App's own fallback is the generic error string, so the OAuth 2.0 wording the tester saw originated server-side. The most likely explanation, consistent with NetSuite - 2FA required to connect landing at the same time on the same account, is that this workspace's connection runs on the new OAuth 2.0 / REST transport from the in-progress migration in R4: Make REST + OAuth 2.0 the default for new NetSuite connections, and the tax import for that transport (or the NetSuite account's OAuth 2.0 / REST Web Services feature configuration) is not yet working on staging.Next steps, all outside the App diff:
requestIDfrom the failingUpdateNetSuiteSyncTaxConfigurationrequest (visible in the video attachment / browser network tab) so the server-side error and its NetSuite error code can be read directly.cc @yuwenmemon @akinwale — owners of the NetSuite OAuth 2.0 work, for context on (2). No blame implied: no PR in this checklist is involved.
akinwale commentedon Sep 17, 2026
This is intentional. Tax-related imports have not yet been implemented for NetSuite connections over OAuth.
6 remaining items
melvin-bot commentedon Sep 29, 2026
@yuwenmemon 10 days overdue. Is anyone even seeing these? Hello?
melvin-bot commentedon Oct 1, 2026
@yuwenmemon this issue was created 2 weeks ago. Are we close to a solution? Let's make sure we're treating this as a top priority. Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!
melvin-bot commentedon Oct 1, 2026
@yuwenmemon 12 days overdue. Walking. Toward. The. Light...
yuwenmemon commentedon Oct 2, 2026
This is fixed. The RESTlet is released. Can we please retest?
melvin-bot commentedon Oct 9, 2026
@yuwenmemon — to hire @applausebot on Upwork, add the External label so a job is created and the offer is sent automatically.
melvin-bot commentedon Oct 26, 2026
This issue has not been updated in over 15 days. @yuwenmemon, @applausebot eroding to Monthly issue.
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!