Change Document: v2.3.6.0 — Insert Diagnostic Telemetry (ISSUE-12 Investigation)
| Field | Value |
|---|---|
| Version | 2.3.6.0 |
| Date | 2026-03-09 |
| Extension | BC Dialing Application (Cambay Solutions) |
| Severity | High — diagnostic release to capture exact NavPermissionException detail |
| Status | Compiled — 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:
- 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. - 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.
- 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
| # | Severity | Category | Description |
|---|---|---|---|
| 1 | High | Added | TryInsertCustomer [TryFunction] procedure on Page 80000 — catches NavPermissionException from Insert(true), logs exact error text as BCDIALER-0021, re-raises |
| 2 | High | Added | TryInsertCustomer [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.alsrc/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:
| Field | Value |
|---|---|
eventId | BCDIALER-0021 |
message | Full NavPermissionException text, e.g. "You do not have the following permissions on TableData Default Dimension: Insert" |
customDimensions.Source | Pag-80000 or Pag-80003 |
customDimensions.ErrorCode | BC error code string |
severity | Error |
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:
| Object | ID | Type | Status | Description |
|---|---|---|---|---|
| ReceivePhoneNumber | 80000 | Page | Modified | Added TryInsertCustomer [TryFunction], BCDIALER-0021 telemetry |
| ReceiveEmail | 80003 | Page | Modified | Added 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-0021in Application Insights (KQL above) within 5 minutes. Themessagefield will contain the exact object and permission type that is failing. - Post-deployment action: Once the
BCDIALER-0021message is retrieved, identify the failing object and implement v2.3.7.0 with the targeted fix. - Removal: The
TryInsertCustomerwrapper should be replaced with a plainNewCust.Insert(true)call once the root cause is resolved and confirmed. Keeping a permanent[TryFunction]wrapper aroundInsertwould 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-0021is addressed in v2.3.7.0. - Error re-raise —
Error(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.