Skip to content

Salesforce Integration Troubleshooting

Section 7 of the Salesforce integration guide. Start at the overview.

Symptom Cause
invalid_grant on JWT exchange User not pre-authorised on the app, cert/key mismatch, aud pointing at login.salesforce.com for a sandbox, or clock skew
Username-Password Flow Disabled Something still on the retired flow — see 2. Authentication
No such column 'Secure_Privacy_Subject_Id__c' Field-level security, not a missing field. Check that first, then check the API name matches exactly
INVALID_SESSION_ID repeating Session refresh not wired up
REQUEST_LIMIT_EXCEEDED Org daily allocation exhausted, often by a backfill. Check Setup → System Overview
HTML where JSON was expected, on a 200 Missing Accept: application/json. The service content-negotiates and will happily serve you a debug page
Redirect to /api/login Request was not authenticated. This endpoint can redirect rather than return 401, so set redirect: 'manual'
200 with a ResponseStatus body and no PagedResults An API error reported inside a success status — e.g. ApiKey does not exist. Check the envelope, not just the status
Consents counted as written but missing from Salesforce Batch upsert results not inspected. A rejected row returns quietly unless you check success on each result
Salesforce datetime fields full of nonsense Created written through unparsed. It is /Date(1787663774128)/, not ISO 8601
Some consents silently dropped Code validating the format of ClientId. It is opaque — store what you are given
Whole consent history duplicates after an org move Consent key built from IndividualId, which changes between orgs — see 6. Writing consent
One person appears under two identities CustomUserId written with inconsistent casing. Normalise the email on both the linking call and the match
Everything resolves to anonymous The site is not calling the linking endpoint. Measure coverage before assuming the sync is broken
403 from /api/consents DomainId does not belong to the authenticated account
429 from Secure Privacy 40/second, 1200/minute per domain. Wait for the period in Retry-After
Consent records dated today CaptureDate set to new Date() instead of the record’s Created
Category mapping stops matching some visitors Mapped on the display name. It follows the visitor’s locale and is editable, so one CategoryId arrives under several names
Acceptances sync, withdrawals do not Extract filtered by Status, or dates compared against Created rather than LastUpdated
Records read twice or missed part-way through a run No fixed date range. Set both FromDate and ToDate
A failed record never retried Watermark advanced despite failures in the pass. Hold it back — re-reading is safe