The recovery action depends on root cause, not just status. Match the user's situation to one of these:
A. Transient failure (network blip, temporary API outage)
- Data synced so far is still valid.
- Action:
external-data-schemas-reload to retry using the configured sync method.
- Incremental/append syncs pick up where they left off.
B. Credentials expired or rotated
- Every schema under the source is failing with an auth error.
- Action: user rotates creds →
external-data-sources-partial-update with the new job_inputs → the reload happens
automatically when the source status flips back to running, or trigger manually with external-data-sources-reload.
C. Schema drift — column renamed, dropped, or type changed
- Error mentions a specific column that no longer matches the source.
- Action:
external-data-schemas-incremental-fields-create to get the current fields, then
external-data-schemas-partial-update with the corrected incremental_field / incremental_field_type /
primary_key_columns. Usually no need to wipe data.
C2. Added / renamed tables in the source database
- User mentions "I added a new table to Postgres but it isn't appearing", or a source table was renamed.
- Action:
external-data-sources-refresh-schemas to pick up the new table list, then configure sync on any new
schemas.
D. Incremental state is wrong (duplicates, missing rows, data looks corrupt)
- Schema status may be
Completed — this isn't a "failure" per se, it's bad data.
- Action:
external-data-schemas-resync to wipe synced data and re-import from source. Destructive but often the
right call for data-quality issues.
E. CDC pipeline broken on Postgres
- Error mentions replication slot, publication, WAL.
- Action:
external-data-sources-check-cdc-prerequisites-create to enumerate what's broken, fix on the Postgres
side, then external-data-schemas-reload. If the WAL position was lost, a resync is sometimes unavoidable.
F. Sync is stuck in Running for hours
- Check
last_synced_at. If it's hours old and still Running, the job is orphaned.
- Action:
external-data-schemas-cancel to stop it, then external-data-schemas-reload.
G. Table data is corrupt but you want to keep the schema config
- Action:
external-data-schemas-delete-data to drop the synced table but preserve the schema entry. Next reload
re-imports from scratch without losing the configured sync_type/incremental_field.
H. Billing limit
- Action isn't technical. Explain the limit, recommend upgrading the plan or disabling lower-priority schemas so the
important ones fit under quota.
I. Webhook-backed schema isn't receiving events
- Symptoms: schema has
sync_type: "webhook", initial bulk sync finished, but no new rows arrive despite activity on
the source side. Status may still read Completed because the bulk sync (the safety-net cadence) is succeeding —
the problem is the push path.
- Action:
external-data-sources-webhook-info-retrieve({source_id}).
- If
exists: false → the webhook was never registered, or was deleted. Call create-webhook-create to
register it.
- If
exists: true but external_status.error is set → typically "API key doesn't have permission to read
webhooks" or similar. The webhook may have been deleted on the source's dashboard. Re-create it.
- If
external_status.status isn't "enabled" → the source disabled the webhook (usually after repeated
delivery failures). Re-enable or re-register.
- If payloads are arriving but failing signature verification → the signing secret was rotated. Get the new
one from the source's dashboard and call
update-webhook-inputs-create({source_id}, {inputs: {signing_secret: "..."}}).
- After any fix, check the source's webhook logs (on their side) to confirm PostHog is now responding 2xx.