Skip to content

fix(ms-bing-ads-audiences): surface real Bing API errors in createAudience#3846

Open
harsh-joshi99 wants to merge 1 commit into
mainfrom
stratconn-bing-create-audience-error-handling
Open

fix(ms-bing-ads-audiences): surface real Bing API errors in createAudience#3846
harsh-joshi99 wants to merge 1 commit into
mainfrom
stratconn-bing-create-audience-error-handling

Conversation

@harsh-joshi99

Copy link
Copy Markdown
Contributor

Summary

The createAudience flow for Ms Bing Ads Audiences was masking the actual cause of create failures, producing opaque errors that made customer issues (e.g. STRATCONN / legalzoom-prod) impossible to diagnose from logs.

Two distinct gaps:

  1. Untyped HTTP failures escaped uncaptured. The POST /Audiences call had no error handling. When Bing returned a non-2xx (often an empty / non-JSON body), the request client threw a raw error that bubbled up untyped — the platform reported it as a generic 500 / INTERNAL / "Bad Request" with an empty responseFromDestination, so Bing's real status/body was never logged.
  2. Unrecognized PartialErrors were swallowed. Bing returns 200 with a PartialErrors array for most create failures. Only the Terms & Conditions code was handled; every other code (e.g. a duplicate audience name) fell through to the opaque NO_AUDIENCE_ID error, discarding Bing's actual ErrorCode/Message.

Changes

  • Wrap the POST /Audiences call in try/catch; on HTTPError, capture Bing's actual status and response body in the thrown error so the real cause is visible in logs (and the downstream sendGXRequest-error payload).
  • Classify 5xx as RetryableError (relays status: 500 downstream as transient); other non-2xx as IntegrationError carrying Bing's status.
  • Surface every non-T&C PartialError with Bing's own ErrorCode and Message instead of collapsing into NO_AUDIENCE_ID.
  • Add a safe readResponseBody helper that never throws on empty / non-JSON bodies.

Contract notes

  • createAudience still returns AudienceResult = { externalId: string } on success — unchanged. Failures are thrown, per the framework contract.
  • The thrown error's status / code / message are exactly what external-audience-service's gxClient logs, so this directly improves the Grafana visibility for these failures.

Testing

  • Added unit tests asserting error type, status, and code for the non-2xx (400), 5xx, and unrecognized-PartialError paths.
  • All 32 tests in the destination pass; lint clean.

🤖 Generated with Claude Code

…ience

Previously createAudience swallowed Bing Ads API failures into opaque
errors: a non-2xx response (often empty/non-JSON body) escaped as an
untyped error that the platform reported as a generic "500 / Bad Request"
with no detail, and any PartialError other than the Terms & Conditions
case fell through to "No AudienceId returned" (NO_AUDIENCE_ID), discarding
Bing's actual ErrorCode/Message.

Changes:
- Wrap the POST /Audiences call in try/catch; on HTTPError, capture Bing's
  actual status and response body so the real cause is visible in logs.
- Classify 5xx as RetryableError (relays status:500 downstream as transient)
  and other non-2xx as IntegrationError with Bing's status.
- Surface every non-T&C PartialError with Bing's own ErrorCode and Message
  instead of collapsing into NO_AUDIENCE_ID.
- Add a safe readResponseBody helper that never throws on empty/non-JSON.

Adds unit tests asserting error type, status, and code for the
non-2xx (400), 5xx, and unrecognized-PartialError paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@harsh-joshi99 harsh-joshi99 requested a review from a team as a code owner June 24, 2026 13:40
Copilot AI review requested due to automatic review settings June 24, 2026 13:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.

Improve diagnosability of createAudience failures for the Ms Bing Ads Audiences destination by surfacing Bing’s actual HTTP/PartialErrors (status/body/ErrorCode) instead of opaque generic errors.

Changes:

  • Add safe(ish) error-body extraction and wrap POST /Audiences to rethrow typed IntegrationError / RetryableError with Bing status + body.
  • Surface non–T&C PartialErrors using Bing’s ErrorCode and Message.
  • Add unit tests for non-2xx, 5xx retryable behavior, and unrecognized PartialError handling.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
packages/destination-actions/src/destinations/ms-bing-ads-audiences/index.ts Add HTTP error handling + PartialErrors surfacing to improve logging/observability and retry semantics.
packages/destination-actions/src/destinations/ms-bing-ads-audiences/tests/index.test.ts Add unit tests covering new error paths and retryable classification.

Comment on lines +21 to +30
const readResponseBody = async (response?: Response): Promise<string> => {
if (!response) {
return ''
}
try {
return (await response.text()) ?? ''
} catch {
return ''
}
}
Comment on lines +131 to +133
const message = `Failed to create audience. Microsoft Bing Ads returned HTTP ${status ?? 'unknown'}: ${
body || 'no response body'
}`
Comment on lines +120 to +126
await expect(testDestination.createAudience(createAudienceInput)).rejects.toThrowError(
new IntegrationError(
'Failed to create audience: CampaignServiceDuplicateAudienceName: An audience with this name already exists.',
'CampaignServiceDuplicateAudienceName',
400
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants