> ## Documentation Index
> Fetch the complete documentation index at: https://gtmsdk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Fix: company domain backfill classifies Attio's server-side domain rejections

> The domains PATCH guard caught AttioValidationError — a repo-local type the SDK never raises — so server-rejected values surfaced as row failures instead of unresolved; a live-captured classifier now maps them to the domain_invalid noop.

## Bug fixes

**Dead exception guards around the company domains PATCH (issue #888)**

`set_company_domain_if_empty` and its enrichment caller each guarded the
domains PATCH with `except AttioValidationError` — a repo-local type the
Attio SDK never raises. The live PATCH raises an SDKError-typed
`ResponseValidationError`, so the intended `domain_invalid` classification
never fired: a domain the server rejected (an RFC-2606 reserved TLD like
`acme.test`, which passes the client-side hostname-shape check) surfaced as
`action="failed"` instead of `unresolved`.

The real 400 body was captured live against the dev workspace: Attio rejects
such values with `code: "validation_type"` and a message naming slug
`"domains"` — a code outside the SDK endpoint's `Literal` union, which is why
it arrives wrapped in `ResponseValidationError` at all. The new
`is_domain_value_rejection` classifier in `libs.attio` (exported alongside
`is_uniqueness_conflict`) re-parses that body and maps it to the same
`domain_invalid` noop the formatter path uses, without the post-failure
re-read: a rejected write landed nothing, so there is no race to
disambiguate. Non-matching SDK errors keep the existing recheck/classify
flow — uniqueness conflicts still raise `AttioConflictError`, anything else
still bubbles. The caller's dead branch is gone; the envelope translation
already maps `domain_invalid` to `unresolved`.

The old test pinned the dead branch by injecting a synthetic
`AttioValidationError` the real callee never raises. It now runs the real
`set_company_domain_if_empty` against a mocked client whose PATCH raises the
captured error, exercising the PATCH → SDKError → `domain_invalid` →
`unresolved` flow end to end, with a companion pin that non-matching SDK
errors still surface as `failed`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.