← Back to Blog

ArcGIS Pro geodatabase guardrails are not interchangeable — what domains, subtypes, contingent values and attribute rules do when a script writes the data

A code icon on the left sends three rows toward a blue shield with a check mark: two blue rows pass through, and a gray row is stopped at an X, with a dashed line back to the shield. Four panels across the top feed the shield: a set of shape symbols, a layer stack splitting into two tables, paired fields marked with two checks and one X, and a gear feeding a table. Past the shield the rows land in a database, and a magnifier panel on the right inspects the stored table, marking two rows with checks and one with an X.

On September 16, 2026, the ArcGIS Blog published Esri’s advice on building better data management workflows in ArcGIS Pro, and its central move is to put repeatable decisions into the data model. It gives each control a job: “domains limit individual values, subtypes organize categories of features, contingent values manage valid combinations, and attribute rules apply logic.” The documentation agrees with that division of labor. What the blog does not answer is the question that matters the day a script loads the data: which of these controls stops a bad value that never went through an editing form?

We read every control against the ArcGIS Pro 3.7 documentation, then measured every control except batch calculation rules on a file and a mobile geodatabase. We did not build a batch calculation rule, so what we say about that rule type is documented, not measured. Where we say measured, we ran ArcGIS Pro 3.7.1 (build 1901, Advanced license) against a fresh file geodatabase and a fresh mobile geodatabase, and both gave the same answer unless we say otherwise. We had no enterprise geodatabase and no ArcGIS Enterprise, so everything we say about those is documented, not tested.

The short answer: at the tools’ defaults, domains, subtypes and contingent values stopped none of the bad values we wrote with an arcpy.da.InsertCursor, the Calculate Field tool or the Append tool. A constraint attribute rule stopped the violating writes from all three. ENFORCE_DOMAINS, an option on the Calculate Field, Calculate Fields and Append tools, changes that for domains, and only for domains — and on a range field with a default, Append replaced a refused value with one that still broke the domain.

Six controls, three points where they act

Attribute rules come in three types — calculation, constraint and validation — and a calculation rule can be immediate or batch. Esri’s overview calls attribute rules “complementary to existing rules used in the geodatabase, such as domains and subtypes,” not a replacement for them. Here is what each control does and when the documentation says it acts.

ControlWhat it doesWhen it acts
Domain Limits a field to a list of coded values or a numeric or date range. A coded value stores a code and shows editors a readable description In the editing application: drop-down lists for coded values, automatic validation during editing for ranges
Subtype Categorizes the features in one class; each subtype can carry its own default values and its own domains Defaults are set on a feature when it is created, before any rule runs
Contingent values Make the valid values of one field depend on the value of another In the editing application, whenever a value is placed in a field
Immediate calculation rule Populates attributes automatically During the edit operation, first
Constraint rule Rejects an edit that fails its condition, returns its own error number and message, and rolls the edit back During the edit operation, after the calculation rules
Batch calculation and validation rules Batch calculation calculates values later; validation finds features that break a requirement and records an error for each. Neither blocks the edit When you evaluate them

Read the last column again. Domains and contingent values act at the same point, inside the editing application (the Attributes pane and the table view, what the rest of this post calls the editing form). Immediate calculation and constraint rules both act on the edit itself, calculation first. Batch calculation and validation rules wait until someone evaluates them. Subtypes are not an enforcement point at all: they supply the categories, the defaults and the per-subtype domains that the other controls use.

The sentence that reads like a guarantee

The domains overview in the Pro help says: “In other words, the field will not accept a value that is not in that domain.” The Domains toolset page is more specific about where that happens: “Validation for coded value domains is accomplished by restricting field values in drop-down lists. Range domains are automatically validated during editing.” Our measurements, below, are consistent with the toolset page, not the overview.

Contingent values are documented the same way. Their restrictions are enforced “in the application whenever a value is placed in a field while editing, such as in the Attribute pane or the Attribute Table view,” and an individual feature edit cannot be completed while it holds an invalid combination. Even the ArcGIS Blog post hedges: with contingent values, an incompatible combination is “less likely to enter the workflow.”

What we wrote, and what got stored

We built a small water pipe class that uses every control the blog names; to keep the test simple, the pipes were stored as points. It had a Material coded-value domain (codes 1 to 3, with descriptions such as PVC and Ductile iron), a Lining coded-value domain, and a Diameter range domain of 2 to 48. A subtype field split the pipes into Main and Lateral, with diameter defaults of 8 and 4 and domains assigned per subtype. A restrictive field group allowed only four material and lining pairs. On top sat three attribute rules: an immediate calculation rule that writes a label, a constraint rule that requires a pressure zone, and a validation rule saying that pipes with a diameter of 24 or more must be ductile iron. For the default-value and ENFORCE_DOMAINS tests we also built smaller classes, among them one with the same Material domain and 2-to-48 Diameter range domain but no subtypes, whose diameter field had a field-level default of 6.

The constraint rule is the blog’s own example: “A water utility uses a constraint rule to require a pressure-zone value whenever a pipe is created or updated. If the value is missing, the edit cannot be saved…”

Then we wrote bad values into the class three ways: an insert cursor, Calculate Field, and Append loading from a staging class that had no constraints of its own. Each ran at its defaults, except Append’s schema_type, which we set to NO_TEST.

Bad valueInsertCursorCalculate FieldAppend
A material code outside the domain StoredStoredStored
A diameter outside the range StoredStoredStored
A subtype code that is not defined (7) StoredStoredStored
A material and lining pair the restrictive field group forbids StoredStoredStored
A missing pressure zone (the constraint rule) Refused with a RuntimeError The tool failed with ERROR 004111 and changed no rows That row skipped with a warning; the other rows loaded

None of the first four rows raised an error or a warning. The immediate calculation rule ran on those writes too: it recomputed the label on cursor inserts, on Calculate Field and on Append.

The geoprocessing reference is candid about the defaults. Calculate Field’s enforce_domains parameter defaults to NO_ENFORCE_DOMAINS: “Field domain rules will not be enforced. This is the default.” Append says the same of the target’s field domains. The insert cursor has no such parameter at all; its optional arguments are datum_transformation, explicit and load_only.

Pro does document how to find domain violations after the fact. In the Attributes pane, Select Only Invalid Objects filters the current selection to the features whose values violate the rules of the geodatabase, such as a nullable field, a relationship rule or an attribute domain. The table view can highlight invalid contingent combinations, and the help describes that cue by color only: red for restrictive field groups, yellow for the rest. Both depend on a person going to look. Pro’s editing options also include attribute validation, which governs the domain and null checks in the Attributes pane, and an editor who needs to override domain values can turn it off.

ENFORCE_DOMAINS: the geoprocessing switch, and what it leaves out

Calculate Field, Calculate Fields and Append each take enforce_domains. Set to ENFORCE_DOMAINS, it changes what those tools do with an out-of-domain value, and Append handles it differently from the two calculate tools.

So ENFORCE_DOMAINS is a choice the person writing the load makes, call by call. It is not a control the data owner can switch on for everyone who writes to the class.

Subtype defaults and the cursor: omit the field, do not pass None

The InsertCursor reference says: “When a field has a default value, a cursor applies the default value when the field is not specified or is set to None.” We measured both kinds of default.

If a script should pick up subtype defaults, leave those fields out of the cursor’s field list rather than sending None.

The guardrail that held: constraint rules

The constraint rule documentation is short: “If a constraint rule is violated, a user-defined error number and message are returned, and the feature edit is rolled back.” The page describing when rules are evaluated says they run when you edit data in ArcGIS Pro or through a feature service, and does not say whether cursor or geoprocessing writes trigger them. We measured the rules against both. Our pressure-zone rule, which returns error 5001 with the message Pressure zone is required, acted on all three writers:

The rule’s message is what an editor sees when an edit is refused, so write it as an instruction a person can act on, as Pressure zone is required does, rather than as a code.

Plan a change window before you add or alter a rule. Creating an attribute rule requires an exclusive lock on the underlying dataset, and so does changing one; rule properties that cannot be modified are read-only, and changing those means deleting the rule and re-creating it. Schedule that work rather than fitting it in while editors are in the data.

Making a constraint rule check the domain

If values reach your data without passing through an editing form, a constraint rule can check the domain for them. Arcade’s Domain() and Subtypes() are Core bundle functions, available since Arcade 1.11, and the Attribute Rule Constraint profile includes the Core bundle. When a feature belongs to a class with subtypes, Domain() returns the domain assigned to the feature’s subtype, so one expression covers per-subtype domains. Each domain expression assumes the domain type it checks: the material rule reads the coded values that only a coded-value domain has, and the diameter rule reads the minimum and maximum that only a range domain has. These are the three expressions we ran. Each is its own rule: paste one expression per rule, never the three together.

Rule dom_material, error 5101: a coded-value check.

var v = $feature.material;
if (IsEmpty(v)) { return true; }
var d = Domain($feature, 'material');
if (IsEmpty(d)) { return true; }
for (var i in d.codedValues) {
  if (d.codedValues[i].code == v) { return true; }
}
return false;

Rule dom_diameter, error 5102: a range check.

var v = $feature.diameter;
if (IsEmpty(v)) { return true; }
var d = Domain($feature, 'diameter');
if (IsEmpty(d)) { return true; }
return v >= d.min && v <= d.max;

Rule dom_ptype, error 5103: a subtype check.

var v = $feature.ptype;
var s = Subtypes($feature);
if (IsEmpty(s)) { return true; }
for (var i in s.subtypes) {
  if (s.subtypes[i].code == v) { return true; }
}
return false;

Each was added as a constraint rule triggered on insert and update, with its own error number and message. For this test the Lateral subtype had a narrower diameter range, 2 to 8, than Main’s 2 to 48. At the tools’ defaults, measured:

Know the limits of these rules before you rely on them:

A load that succeeds can still have refused rows

When Append skipped a row that broke a constraint rule, it raised no exception. It returned status 4, which the Result reference defines as Succeeded, with Result.maxSeverity of 1 and arcpy.GetMaxSeverity() of 1, which the GetMaxSeverity reference defines as “The tool returned a warning message, but not an error message.” A clean Append returned status 4 with a maximum severity of 0. The runs with ENFORCE_DOMAINS that refused values also finished with a maximum severity of 1. A loader that only catches exceptions reports all of these as clean.

So read Result.maxSeverity or arcpy.GetMaxSeverity() after every tool, and compare rows in with rows added. Two more measured details make the checking harder than it should be:

Inside an edit session

An edit session changes what a refusal costs. The arcpy.da.Editor reference says that when it is used as a with block and an exception occurs, editing is stopped but not saved. Measured: an uncaught constraint refusal inside the block discarded the rows already inserted in that session. Catching the RuntimeError row by row inside the session kept the valid rows. That discard is the rollback our weekly CSV mirror relies on, and it means one row that breaks a constraint rule throws away the whole run there. If your rows are independent of each other, catch the error per row instead, and log and count the refused rows so the load cannot drift silently.

Validation and batch calculation rules run when you evaluate them

Validation rules do not block edits. The Add Attribute Rule reference says existing features are identified with a batch validation process, at a user-defined time, and that “when a rule is violated, an error feature is created.” Our validation rule let 36-inch PVC pipes load without complaint. Evaluate Rules on the file geodatabase then reported 15 rows evaluated and 7 errors identified, stored in GDB_ValidationPointErrors because our test pipes were points. The documentation says the error datasets are created with the first batch calculation or validation rule, and that error features can be reviewed in the Error Inspector during quality assurance. A Validation Status field arrives with the first rule of either type and tracks, row by row, whether calculation or validation is still required and whether the row has errors.

A few documented conditions apply:

One measured trap on a mobile geodatabase: an Evaluate Rules run with no extent evaluated only 10 of our 15 rows. The five it skipped lay outside the feature class’s stored extent and stayed marked as needing validation; a second run reported Rows evaluated: 0. The tool reference says that for a file or mobile geodatabase the entire workspace is evaluated, and on the file geodatabase it was. Passing an explicit extent evaluated the missing rows. The same page names a second filter that stacks on top of the extent: if there is a selection in the map, only selected features within the specified extent are evaluated. We did not establish why the stored extent was out of date, so on a mobile geodatabase, compare the evaluated count with the row count.

Enterprise geodatabases, ArcGIS Online and the web

The ArcGIS Blog post carries one note that decides a great deal: “File and mobile geodatabases support all three rule types. For enterprise geodatabases, batch calculation and validation rules require the dataset to be branch versioned and published as a feature service with the Validation enabled.” The documentation confirms the branch-versioning requirement, qualifies the Validation one, and adds the parts that decide a budget:

ArcGIS Online. The Pro help is direct: “Attribute rules are not transferred when you publish datasets to an ArcGIS Online portal.” We found no other ArcGIS Online route for attribute rules in the documentation we read, and we did not publish to test it. If you load data into hosted feature layers published from Pro, plan on the rules not being there, and put the checks in the loader. For a team with ArcGIS Online and ArcGIS Pro but no ArcGIS Enterprise, the documentation offers two places the rules run. One is Pro editing a file or mobile geodatabase, which supports all three rule types. The other is an app built with a Native SDK editing a stand-alone geodatabase exported from Pro and side-loaded onto the device, where only constraint and immediate calculation rules run (see the next list). Budget for that route: a Native app needs a production license, and editing a stand-alone mobile geodatabase created with ArcGIS Pro sits at the Basic level, not Lite. The documented way to download rules into a sync-enabled geodatabase needs ArcGIS Enterprise 11.4 or later feature services. Neither route puts a rule on data hosted in ArcGIS Online. Domains are another matter: they are visible on a hosted layer’s fields, and we showed how to read them in the data dictionary post. One exception covers the schema this article builds: if you publish a hosted feature layer from ArcGIS Pro that contains subtypes with associated domains on other fields, you cannot view or edit those domains in ArcGIS Online.

What a service does with a bad domain value is not documented where we looked. The Apply Edits reference we read does not mention domains or contingent values, and we did not test one. Whether a feature service rejects an out-of-domain value, an undefined subtype code or a forbidden combination is, as far as this post goes, unknown.

Which clients evaluate the rules

Exclude from application evaluation is not a way around a rule. It moves the evaluation from the client to the data source, where the rule still runs. It must be on for an immediate calculation rule whose expression returns certain attribute rule dictionary keywords, uses sequences, or uses the field value in the calculation, and it does not apply to validation or batch calculation rules.

What it costs, and who can do it

TaskArcGIS Pro license level
Create domains, subtypes, field groups and contingent values Basic, Standard or Advanced
Add attribute rulesStandard or Advanced (Basic: no)
Disable or enable attribute rules with the Disable Attribute Rules and Enable Attribute Rules toolsStandard or Advanced (Basic: no)
Evaluate RulesStandard or Advanced; Basic is limited to branch-versioned data under ArcGIS Enterprise named user licensing, with the Advanced Editing user type extension. On branch-versioned data in ArcGIS Enterprise 11.2 or later, every level also needs that extension

On Pro Basic, from a web feature layer, or over a database connection as anyone other than the data owner, the Attribute Rules view is read-only. The table speaks in license levels, so check which ArcGIS Pro license level each person has before you plan rule work.

Data Reviewer is separately licensed. The ArcGIS Blog post suggests starting with Data Reviewer’s Run Data Checks tool and never says it is separately licensed. In ArcGIS Pro, Data Reviewer is available for all license levels as an add-on to a Named User, Single Use or Concurrent Use license. Creating, modifying or evaluating Data Reviewer-based attribute rules in a file or mobile geodatabase needs a Data Reviewer license and Pro Standard or Advanced, and the Ready to Use Rules gallery also needs a Data Reviewer license. In ArcGIS Enterprise, a web feature layer with the Validation capability over datasets with Data Reviewer-based rules needs the Data Reviewer server extension, a CPU-based license for each GIS Server federated with the organization, available for the Standard and Advanced editions of ArcGIS GIS Server. Check your own entitlement before you plan on it.

Credits. We found no ArcGIS Online credit cost for domains, subtypes, contingent values, attribute rules, Evaluate Rules or error datasets in any page we read. The costs are licenses and platform. Batch calculation and validation rules on enterprise data need ArcGIS Enterprise, a branch-versioned enterprise geodatabase and the Advanced Editing user type extension. From ArcGIS Enterprise 11.2, every member who evaluates them needs that extension, and the ArcGIS Enterprise licensing page says members who use attribute rules or branch versioning through web feature layers must be assigned it.

Compatibility. Adding attribute rules raises the dataset’s minimum client to ArcGIS Pro 2.1, so it is no longer available in ArcMap. Contingent values make a dataset incompatible with ArcMap and with releases before ArcGIS Pro 2.3 and ArcGIS Enterprise 10.7.x. Copy and paste and XML workspace documents carry attribute rules; Feature Class To Feature Class and Table To Table do not.

Who the guardrails do not stop

In an enterprise geodatabase, attribute rules are added as the data owner, and only the domain’s owner or the geodatabase administrator can change a domain. Rules can also be switched off. Esri documents disabling attribute rules on a dataset, from the Attribute Rules view or with the Disable Attribute Rules and Enable Attribute Rules tools, and gives the reason: it “can improve performance for bulk data loads.” On our file and mobile geodatabases it works: we disabled the pressure-zone rule, appended a row with no pressure zone, re-enabled the rule, and the row stayed. The two tools need Pro Standard or Advanced. For a file or mobile geodatabase, that license level is the only condition the tool pages put on running them; they name no data owner or other role there.

Two consequences follow. First, immediate rules add work to every edit that triggers them, which is why the documentation suggests switching them off for bulk loads; we did not time it. The documentation names other levers when evaluation cost becomes the problem. Order the cheap constraint rules first, so evaluation fails early rather than after the complex ones, and migrate the error tables, which default to 32-bit ObjectIDs, once the values pass that range. Large service evaluations already run asynchronously through the ValidationTools geoprocessing service by default, an option that needs a feature service with the Validation capability. While the rules are off, they are off for the dataset, so every writer is unguarded by those rules until they are back on. A load that disables them has to do its own checking, or evaluate a validation rule afterward, and it has to re-enable them in a finally block so a failed run does not leave them off. Second, every writer we tested was ArcGIS software, and the documentation describes rules running in ArcGIS Pro, feature services and Native apps. It does not say rules run for writes made outside ArcGIS, so test any such writer before you count on a rule. A constraint rule guards the data against writers that go through ArcGIS, not against whoever can disable it. The control designed to review data that is already stored is a validation rule, which identifies existing features at a time you choose.

Before you rely on a guardrail

  1. List every writer, not just the editors. The editing form is only one of the ways values arrive: scripts, geoprocessing tools, scheduled loads and services are others. Note which of them are not ArcGIS software, and test any such writer before you count on a rule.
  2. Put the values your ArcGIS writers must not store in constraint rules, and remember that whoever can disable a rule can load what it would refuse. If loads bypass the editing form, add Domain() and Subtypes() checks, decide on purpose whether an empty value passes, and fix existing violations before the rules go on. If a large load switches the rules off for speed, the load does the checking and turns them back on even when it fails.
  3. Decide on ENFORCE_DOMAINS call by call. Append keeps the row and replaces the refused value: with null, or, measured, with 0 on a range field that has a default, and that 0 can itself be out of range. For rows it updates through matching fields, it leaves the target field unchanged instead. The parameter checks neither subtype codes nor contingent values.
  4. Leave fields out of an insert cursor when you want their subtype defaults.
  5. Check the maximum severity after every tool, and compare row counts: when Append skips a row, or a tool run with ENFORCE_DOMAINS refuses a value, the result is a warning, not an exception. Counts alone miss an ENFORCE_DOMAINS Append, which keeps every row.
  6. Inside an edit session, catch refusals per row if one bad row should not discard the rest.
  7. Evaluate validation rules on a schedule, and on a mobile geodatabase compare the evaluated count with the row count.
  8. Know the platform. Rules are not transferred when you publish from Pro to ArcGIS Online, so checks for data you load into hosted layers live in the loader. In an enterprise geodatabase, batch calculation and validation rules need branch versioning; the Validation capability is optional when you share them and required to evaluate them against the service. Budget the Advanced Editing user type extension for every member who uses attribute rules through web feature layers; from ArcGIS Enterprise 11.2 it is required to evaluate batch calculation and validation rules on them. Native apps run only the constraint and immediate calculation rules.
  9. Check licensing. Adding or disabling rules needs Pro Standard or Advanced, so check which ArcGIS Pro license level each person has, and Data Reviewer is a separate license.
If you are not the one writing the scripts. A domain looks like a promise that bad values cannot get in. The documentation puts that check in the editing form. In our tests on file and mobile geodatabases, an insert cursor stored out-of-domain values with no error, and so did a Calculate Field run and an Append, each with domain enforcement left at its default. Those values sit in the data until someone runs a check. If the data lives in ArcGIS Online hosted layers published from Pro, the attribute rules do not go with it. Finding out which of your rules would actually stop a load costs one conversation with whoever builds it and whoever owns the data: which values are protected by constraint rules, whether the load switches the rules off, and what it does with warnings.

The controls are not interchangeable. Domains and contingent values shape what an editor is offered, and subtypes supply categories, defaults and per-subtype domains. Immediate calculation rules fill values and constraint rules refuse the edit, whether it came from an editing form or, in our Pro 3.7.1 file and mobile geodatabase tests, from a cursor or a geoprocessing tool. Batch calculation rules calculate and validation rules report, when you evaluate them. Choose among them by listing who writes the data, not by what the editing form shows.

References

Loading data into a geodatabase someone else designed?

We build ArcPy loads and geodatabase designs that agree about what gets stored — constraint rules on the values a load must not store, loads that read their own warnings. Book a free intro call and we will look at your schema and your writers.

Book a free intro call