ReferenceZendeskDriftGlossary

Zendesk Drift Issue Code Reference

Every issue code, every safe action, and every blocked_reason that g-gremlin zendesk drift can emit. 12 issue codes (6 org, 4 user, 2 ticket). 4 safe Zendesk-side actions. 7 blocked reasons. Use this page to map a finding in exceptions_by_account.csv or apply_receipt.json to its resolution path.

Published April 17, 2026 - Canonical reference for the Zendesk drift audit

Short answer

Three lists. Twelve issue codes, four safe actions, seven blocked reasons.

  • 6 org-level issues (1 critical, 2 high, 3 medium). 2 are auto-prepared as safe actions; 4 are review-only.
  • 4 user-level issues (1 high, 3 medium). 2 are safe-to-apply; 2 are review-only.
  • 2 ticket-level issues. Both are detection-only. Ticket mutation is out of scope in v1.
  • 4 safe actions total: set_org_external_id, add_org_domain, assign_user_to_org, move_user_to_org.
  • Blocked reasons land in apply_receipt.json. No action is ever silently dropped.

The 12 Zendesk drift issue codes

Grouped by scope: 6 org, 4 user, 2 ticket. Each row names the code, its risk, its disposition, the safe action (when applicable), the definition, and the evidence that triggers it.

Org (6)

org_duplicate_external_id

critical review-only

Two or more Zendesk organizations share the same external_id for one Salesforce account. Blocks every downstream user and ticket decision for that account.

Evidence: Multiple Zendesk orgs with identical external_id == sf_account_id.

Resolution guide

org_missing_external_id

high safe-to-applyset_org_external_id

A unique domain-based org candidate has a blank external_id. Gremlin can set it safely to the Salesforce account id.

Evidence: Unique domain-based org candidate plus blank external_id on the target org.

Resolution guide

org_external_id_conflict

high review-only

A likely org candidate has a nonblank external_id that conflicts with the expected Salesforce account. Resolve in Zendesk; Gremlin never overwrites a conflicting id.

Evidence: Unique domain candidate plus conflicting nonblank external_id.

org_missing_expected_domain

medium safe-to-applyadd_org_domain

The resolved org is missing one or more expected domains from the Salesforce effective domain set. Safe to attach when the collision precheck passes.

Evidence: Unique resolved org plus one or more expected domains absent from the org domain list.

org_domain_attached_elsewhere

critical review-only

An expected domain is already attached to another Zendesk org. Blocked with reason domain_belongs_to_other_org; Gremlin never steals domains.

Evidence: Precheck against all org domains shows the domain belongs to another org.

Resolution guide

account_missing_zendesk_org

medium review-only

A Salesforce account has no unique external_id match and no safe domain-resolved target org. Create the org manually, then re-audit.

Evidence: No unique external-ID match and no safe domain-resolved target org.

Resolution guide

User (4)

user_missing_expected_membership

high safe-to-applyassign_user_to_org

A user maps deterministically to an account but is not a member of the expected org. Gremlin adds the membership. It does not change the default org.

Evidence: Non-personal deterministic account resolution plus membership set lacks target org.

user_default_org_not_expected

medium safe-to-applymove_user_to_org

User is already a member of the expected org, but the default org differs. Gremlin promotes the existing target membership to default. It does not add or remove memberships.

Evidence: Membership includes target org, but user.organization_id is not the target.

Resolution guide

user_resolution_blocked_duplicate_external_id

high review-only

The user’s expected account depends on an account/org mapping blocked by duplicate external_ids upstream. Resolve the org-level duplicate first.

Evidence: Upstream org_duplicate_external_id.

Resolution guide

user_domain_ambiguous

medium review-only

A non-personal email domain maps to multiple candidate accounts or orgs. Personal email domains are suppressed from user drift detection entirely.

Evidence: Domain collision across Salesforce accounts or unresolved org ambiguity.

Ticket (2) - detection only

ticket_org_mismatch

medium review-only

A ticket’s organization_id does not match the requester’s deterministically resolved expected org. Detection only; ticket mutation is out of scope.

Evidence: Requester resolution plus ticket org differs or is blank.

ticket_resolution_blocked_duplicate_external_id

medium review-only

Ticket attribution cannot be trusted because the requester’s account resolution is blocked upstream. Detection only.

Evidence: Upstream org_duplicate_external_id.

Resolution guide

The 4 safe Zendesk-side actions

Each action lists its preconditions (all must hold) and the conditions under which Gremlin explicitly blocks it.

set_org_external_id

Set a blank Zendesk org external_id to the Salesforce account id.

Preconditions

  • Exactly one target Zendesk org is resolved.
  • Target org external_id is blank.
  • No other Zendesk org already uses the intended Salesforce account id.
  • Account is not blocked by duplicate external-id ambiguity.

Blocked when

  • Target org already has a conflicting nonblank external_id.
  • Another org already uses the intended Salesforce account id.
Resolution guide

add_org_domain

Append one missing expected domain to the resolved Zendesk org.

Preconditions

  • Exactly one target Zendesk org is resolved.
  • Domain is in the account’s effective domain set.
  • Domain is not already present on the target org.
  • Domain is not a personal/consumer email domain.
  • Account is not blocked by duplicate external-id ambiguity.
  • Precheck confirms the domain is not attached to another Zendesk org.

Blocked when

  • Domain belongs to another org (blocked_reason: domain_belongs_to_other_org).
  • Account is ambiguous.
  • Target org cannot be uniquely resolved.
Resolution guide

assign_user_to_org

Add a missing organization membership for a user. Does not change the default org.

Preconditions

  • User maps deterministically to one expected account and one expected Zendesk org.
  • Account is not blocked by duplicate external-id ambiguity.
  • User is not already a member of the target org.
  • User match did not depend on a personal-email-domain rule.

Blocked when

  • Account ambiguous (duplicate_external_id).
  • User domain is ambiguous across multiple accounts.
  • User is already a member of the target org (no action needed).

move_user_to_org

Make an existing target membership the user’s default org. Does not add or remove membership.

Preconditions

  • User maps deterministically to one expected account and one expected Zendesk org.
  • Account is not blocked by duplicate external-id ambiguity.
  • User is already a member of the target org.
  • Current default org differs from the target org.

Blocked when

  • User is not a member of the target org (would require assign_user_to_org instead).
  • Account ambiguous (duplicate_external_id).
Resolution guide

Blocked reasons in apply_receipt.json

When a prepared action is not applied, Gremlin records exactly why. These are the values you will see in the blocked, skipped, or failed rows of apply_receipt.json.

blocked_reasonApplies toMeaning and resolution
duplicate_external_idevery action on the affected accountThe Salesforce account resolves to more than one Zendesk org. No safe action is prepared until the duplicate is resolved in Zendesk. Fix duplicate external_id in Zendesk.
domain_belongs_to_other_orgadd_org_domainThe domain Gremlin wanted to attach is already attached to a different Zendesk org. Detach manually, then re-audit. Zendesk domain collision between organizations.
user_domain_ambiguousassign_user_to_org and move_user_to_orgA non-personal email domain maps to multiple candidate accounts or orgs. Resolve upstream in Salesforce or Zendesk.
precondition_changed_user_already_memberassign_user_to_orgBetween audit and apply, the user was added to the target org. Gremlin skips the action with an explicit reason.
precondition_changed_external_id_now_setset_org_external_idBetween audit and apply, the target org external_id was set by another system. Gremlin skips without overwriting.
precondition_changed_domain_already_presentadd_org_domainBetween audit and apply, the target org already carries the expected domain. No action needed.
failed_rate_limitedany live-apply actionBounded exponential backoff on HTTP 429 was exhausted. The action is recorded with failure code failed_rate_limited and does not silently drop.

No action is ever silently dropped. Blocked, skipped, and failed rows all carry explicit reason codes.

FAQ

How many issue codes does g-gremlin zendesk drift emit?

Twelve. Six org-level (org_duplicate_external_id, org_missing_external_id, org_external_id_conflict, org_missing_expected_domain, org_domain_attached_elsewhere, account_missing_zendesk_org), four user-level (user_missing_expected_membership, user_default_org_not_expected, user_resolution_blocked_duplicate_external_id, user_domain_ambiguous), and two ticket-level (ticket_org_mismatch, ticket_resolution_blocked_duplicate_external_id). The ticket codes are detection-only and never generate write actions.

Which issue codes are safe-to-apply?

Four. org_missing_external_id is auto-prepared as set_org_external_id. org_missing_expected_domain is auto-prepared as add_org_domain when the collision precheck passes. user_missing_expected_membership is auto-prepared as assign_user_to_org. user_default_org_not_expected is auto-prepared as move_user_to_org. Every other issue code stays review-only by design.

What are the 4 safe Zendesk-side actions in v1?

set_org_external_id (set a blank Zendesk org external_id to the Salesforce account id), add_org_domain (attach a missing expected domain to the resolved org), assign_user_to_org (add a missing organization membership for a user), and move_user_to_org (promote an existing target membership to default). Nothing else is written live. No ticket mutation, no org create/merge/delete, no Salesforce writes.

What does blocked_reason mean in apply_receipt.json?

It is the explicit reason a prepared action was not applied. Common values are duplicate_external_id, domain_belongs_to_other_org, user_domain_ambiguous, and the precondition_changed_* family for actions that became unsafe between audit and apply. failed_rate_limited records exhausted backoff on HTTP 429.

Why does Gremlin keep duplicate_external_id issues review-only?

Because picking the wrong surviving org would quietly corrupt the customer graph. The tool cannot deterministically decide which duplicate is the real org. It needs a human with Zendesk context. This is why org_duplicate_external_id, user_resolution_blocked_duplicate_external_id, and ticket_resolution_blocked_duplicate_external_id are all review-only.

Are personal email domains treated as drift?

No. gmail.com, outlook.com, yahoo.com, icloud.com, hotmail.com, protonmail.com, and similar consumer domains are suppressed from domain-based user drift detection. End-users on those domains are only linked through a deterministic path like an existing membership on a uniquely resolved Zendesk org. They may appear in trace output with suppression_reason = personal_email_domain_suppressed but do not generate domain-drift issues.

Does Gremlin ever overwrite an existing external_id or domain?

No. set_org_external_id requires a blank target external_id. add_org_domain requires a successful collision precheck proving the domain is not attached to another org. When those preconditions fail, the action is blocked and recorded in apply_receipt.json with an explicit reason.

What does Gremlin never do in v1?

Never writes to Salesforce. Never mutates Zendesk tickets. Never creates, merges, or deletes Zendesk organizations. Never removes organization memberships. Never bypasses caps. Never applies live without --apply and a matching --confirm-plan-hash. Never uses fuzzy or LLM-driven matching in the apply path.

Related Zendesk drift pages

Salesforce and Zendesk integration pillar

The audit-first integration contract. Start here if you are new to g-gremlin zendesk drift.

Open page

Zendesk drift playbook

Operator execution log: Slack message, prompt, audit, review, dry-run, apply.

Open page

Audit Zendesk and Salesforce sync from the CLI

The focused CLI walkthrough for the drift audit workflow.

Open page

Fix duplicate external_id in Zendesk

The critical blocker: two orgs share the same external_id.

Open page

Link a Zendesk organization to a Salesforce account

The safe-to-apply path for org_missing_external_id.

Open page

Zendesk domain collision between organizations

What to do when domain_belongs_to_other_org blocks add_org_domain.

Open page

Fix wrong default organization in Zendesk

The safe-to-apply fix for user_default_org_not_expected.

Open page

Salesforce Zendesk comparison

Native sync vs iPaaS vs audit-first CLI, side by side.

Open page

Keep the conversation going

These pages are meant to help operators solve real problems. If you want the next guide, grab the low-friction option. If you need the implementation, not just the guide, book time.

Stay in the loop

Get the next guide when it ships

I publish architecture guides grounded in real implementations. No generic AI filler.

Use your work email so I can keep the list useful and relevant.

Book Mike directly

Need the implementation, not just the guide?

Book a 15-minute working session with Mike right on his calendar. Tooling, consulting, or a mix of both is fine.

Open Mike's calendar

If you want me to come in with context, leave your email and a short note before the call.

I'll route new requests into the internal website inquiries inbox so I can follow up fast.