Troubleshooting
Find the symptom, check the likely cause, then follow the link to the full explanation. This page is an index: the detail lives in the guide for each area.
In short
- Start with Testing your integration: a test key, something published to Test, and one device checked end to end.
- An event batch answers
202even when events are dropped. ReadacceptedanddropReasons. - In the dashboard, Developers → Test mode → Why didn't it show? lists every block for a user or device and the reason each one is hidden. See Why didn't it show?.
A block does not show
Work down this list in order; each step rules out one cause.
| Check | Likely cause and fix | Details |
|---|---|---|
| 1. Key and environment | A live key does not see content published only to Test. Use the matching key, and confirm GET /sync returns your block. | Test and live keys, Check the key |
| 2. Identify | The device was never identified, so segment targeting cannot match. | Identify |
| 3. Consent | Traits and segments are only written while analytics consent is granted. | Without consent |
| 4. Segment membership | The instance targets a segment this person is not in, or the segment has not refreshed yet. | Segment freshness |
| 5. Instance status | The instance is draft or pending review, or published to Test while the app uses a live key. | Block lifecycle, Publish to Test |
| 6. Schedule | Custom, payday and Ramadan windows are evaluated in Asia/Riyadh time, not the device's or the server's zone. | Schedules |
| 7. Frequency cap and cooldown | The person has already seen a popup as often as the rule allows. | Limits, Why didn't it show? |
| 8. Device cache | The device is showing content from its last sync. Refresh, or wait for the next sync. | Refresh, When it doesn't work |
Errors from the API
| You see | Likely cause and fix | Details |
|---|---|---|
401 INVALID_SDK_KEY | The value is not a ContentFlow key, the key was revoked, or the workspace is unknown or suspended. Copy the key again from Developers → Your keys. | Check the key, A rejected key |
TENANT_KEY_MISMATCH | 401 on the SDK gateway (403 on the legacy path): a publishable key was sent with a tenant header that names a different workspace. Remove the header; the key already identifies the workspace. | A rejected key, Keys |
429 SDK_RATE_LIMIT_EXCEEDED | The workspace is over 1,000 requests a minute. The SDK keeps events and retries; a direct caller waits for Retry-After. | Analytics: when it doesn't work |
429 USER_RATE_LIMITED | One person changed consent or registered new push devices too often. Wait for Retry-After; do not loop. | REST guide, API explorer |
Events do not appear in analytics
| Likely cause | Fix | Details |
|---|---|---|
Analytics consent was never granted (consent_not_granted) | Call the consent method from your consent screen. | Reading dropReasons, Analytics consent |
The server dropped the batch (device_not_identified) | Fix identify first. | Analytics: when it doesn't work |
| Batching: events are sent in groups of 10 or every 15 seconds | Wait, or flush explicitly, for example before sign-out. | Events, Flush |
| A test key was used | Test traffic is kept out of live analytics; look in Test mode. | Test mode |
Push and campaign messages
| Symptom | Likely cause and fix | Details |
|---|---|---|
| Push does not arrive | No push permission, no registered token, no push consent, or the token is stale. Check each in order. | Register, Errors, Token hygiene |
| A campaign sent fewer messages than expected | People are skipped for missing consent, missing contact data or blackout windows. The skip reasons are listed per campaign. | Skips |
| A campaign's in-app message is not rendered | It arrives as a block with the key journey_message on the next sync. Your app needs a placement that renders it. | In-app messages, Journeys |
Erasure conflicts
| You see | Likely cause and fix | Details |
|---|---|---|
409 ERASURE_PENDING | An earlier erasure of this device did not finish. Retry the erasure with the same device id first, and identify only after it answers 200. | Erasure |
409 SUBJECT_ERASED | The person's data was erased, so their profile will not be recreated until they grant consent again. | Erasure, Audience erasure |
Strings do not update
A string reaches the app only once it is translated, approved and published, and the app falls back to another locale if the requested one is missing. Check the approval state first, then the locale fallback and the device's last sync.
Every guide's "When it doesn't work"
Next
- Testing your integration: the end-to-end check.
- What is ContentFlow: the overview for non-developers.