Skip to main content

Change Document: v2.3.6.0 — Insert Diagnostic Telemetry (ISSUE-12 Investigation)

FieldValue
Version2.3.6.0
Date2026-03-09
ExtensionBC Dialing Application (Cambay Solutions)
SeverityHigh — diagnostic release to capture exact NavPermissionException detail
StatusCompiled — ready for deployment

Background

v2.3.5.0 deployed to Production on 2026-03-09 (~22:35 UTC) and added Dimension (table 348) to inline Permissions, bringing the total to 34 tables. Integration test results confirmed new customer creation succeeds for the BestwayBCAPI test account (BCDIALER-4001 fired 6 times via TC-PHONE-001 and TC-EMAIL-001). However, post-deployment monitoring of live Nextiva traffic shows the HTTP 403 NavPermissionException rate on new customer creation is still ~50–75%. Breadcrumb telemetry (BCDIALER-0020) confirms the live failure point remains between step 5 ("calling Insert(true)") and step 6 ("Insert complete") — identical to the pre-v2.3.5.0 pattern.

Why the Integration Test Does Not Reproduce the Live Failure

The integration test (tools/bc_dialing_integration_test.py) authenticates to BC using the BestwayBCAPI Azure AD app registration, which is assigned the BCDialerPermissions permission set and D365 Full Access / Dynamics 365 Full access. The live Nextiva calls authenticate using a different Azure AD app registration — the Nextiva platform's own service account. The Nextiva service account's permission sets are unknown: it is not visible in BC's standard Users page via the automation API, and Rob Chowdhury has been asked to provide the Azure AD client ID so it can be located.

Why Further Table Analysis Is Unlikely to Resolve the Issue

34 tables now cover every known table accessed by Customer.Insert(true) through all known event subscriber chains. Despite this, the failure persists for live Nextiva calls but not for the integration test. This strongly suggests the remaining cause is not a missing tabledata permission but one of:

  1. Missing codeunit EXECUTE permission — the BestwayUSA extension codeunits (INVCSalesHandler, INVCMiscIIntegrationHandler, INVCUpdateSalesOrderAreaDimension) require EXECUTE permission. Inline Permissions on API pages cannot grant codeunit EXECUTE — this must come from the user's permission sets.
  2. BC SaaS entitlement restriction — Azure AD app registrations used by third-party integrations (Nextiva) may receive a restricted entitlement license that limits database write operations regardless of permission sets.
  3. Unexpected table not in the current list — the error is thrown by a table or object not yet identified.

The exact error text and object name from the NavPermissionException is the missing diagnostic data. BC's standard RT0008 telemetry event captures only httpStatusCode and failureReason (generic text), not the specific object that caused the permission failure.

Diagnostic Approach

Wrapping NewCust.Insert(true) in a [TryFunction] procedure catches the NavPermissionException before it unwinds the call stack, making the error text and error code available via GetLastErrorText() and GetLastErrorCode(). Logging these as BCDIALER-0021 in Application Insights will produce a telemetry event containing the exact failing table or codeunit name, definitively identifying the root cause for the next fix.


Summary of Changes

#SeverityCategoryDescription
1HighAddedTryInsertCustomer [TryFunction] procedure on Page 80000 — catches NavPermissionException from Insert(true), logs exact error text as BCDIALER-0021, re-raises
2HighAddedTryInsertCustomer [TryFunction] procedure on Page 80003 — same as above

Detailed Changes

1–2. TryInsertCustomer Diagnostic Wrapper — Pages 80000 and 80003

Files modified:

  • src/Page/Pag-80000.ReceivePhoneNumber.al
  • src/Page/Pag-80003.ReceiveEmail.al

Change:

NewCust.Insert(true) on each page is replaced by a call to a new [TryFunction] local procedure TryInsertCustomer. If the insert fails, BCDIALER-0021 is logged to Application Insights with the exact error text and error code before the error is re-raised to the caller.

Before (both pages):

NewCust.Insert(true);

After (both pages):

if not TryInsertCustomer(NewCust) then begin
Session.LogMessage('BCDIALER-0021', GetLastErrorText(),
Verbosity::Error, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher,
'Source', 'Pag-80000', 'ErrorCode', GetLastErrorCode());
Error(GetLastErrorText());
end;

New procedure added at end of each page:

[TryFunction]
local procedure TryInsertCustomer(var NewCust: Record Customer)
begin
NewCust.Insert(true);
end;

Telemetry produced on failure:

FieldValue
eventIdBCDIALER-0021
messageFull NavPermissionException text, e.g. "You do not have the following permissions on TableData Default Dimension: Insert"
customDimensions.SourcePag-80000 or Pag-80003
customDimensions.ErrorCodeBC error code string
severityError

Behavior on success: TryInsertCustomer returns true, BCDIALER-0021 is not logged, and execution continues to step 6 as before.

Behavior on failure: TryInsertCustomer catches the exception, returns false. BCDIALER-0021 is logged with the full error text. Error(GetLastErrorText()) re-raises the exception, which BC converts to HTTP 403 — the caller (Nextiva) receives the same response as before. This release does not change the observable behavior from Nextiva's perspective.

KQL to query BCDIALER-0021 in Application Insights:

traces
| where customDimensions.eventId == "BCDIALER-0021"
| project timestamp, message, customDimensions.Source, customDimensions.ErrorCode
| order by timestamp desc

Why TryFunction Can Catch NavPermissionException

AL [TryFunction] procedures implement structured exception handling at the BC runtime level. NavPermissionException is a BC runtime exception (not a user-facing error dialog), and it is caught by [TryFunction] in the same way as database errors and other runtime errors. After the function returns false, GetLastErrorText() returns the full exception message including the specific table or object name and the permission type (Read/Insert/Modify/Delete/Execute) that was missing.


Object Inventory

No new objects. Modified objects only:

ObjectIDTypeStatusDescription
ReceivePhoneNumber80000PageModifiedAdded TryInsertCustomer [TryFunction], BCDIALER-0021 telemetry
ReceiveEmail80003PageModifiedAdded TryInsertCustomer [TryFunction], BCDIALER-0021 telemetry

Deployment Notes

  • No data migration required — diagnostic telemetry addition only
  • No configuration changes required
  • Backwards compatible — failure behavior from Nextiva's perspective is unchanged (HTTP 403 still returned on failure)
  • Supersedes v2.3.5.0 — deploy this version directly
  • Verification: After deployment, trigger an inbound call to a phone number not in BC. If the 403 failure persists, query BCDIALER-0021 in Application Insights (KQL above) within 5 minutes. The message field will contain the exact object and permission type that is failing.
  • Post-deployment action: Once the BCDIALER-0021 message is retrieved, identify the failing object and implement v2.3.7.0 with the targeted fix.
  • Removal: The TryInsertCustomer wrapper should be replaced with a plain NewCust.Insert(true) call once the root cause is resolved and confirmed. Keeping a permanent [TryFunction] wrapper around Insert would suppress runtime errors that should be visible to callers.

Known Limitations

  • Does not fix the 403 rate — this release captures diagnostic data only. The 403 failure rate will remain unchanged until the root cause identified by BCDIALER-0021 is addressed in v2.3.7.0.
  • Error re-raiseError(GetLastErrorText()) re-raises the exception as a BC UI error. In an API context, BC converts this to HTTP 403, which matches the current behavior. No regression expected.