How to Configure UN Network Datasets in ArcGIS Pro: A Diagnostic & Production-Grade Guide

Configuring an ArcGIS Utility Network (UN) dataset is a deterministic engineering workflow that directly governs trace accuracy, regulatory compliance, and automated asset lifecycle management. Doing it by hand through the Pro UI — clicking through connectivity dialogs, hand-assigning terminals, eyeballing rule matrices — does not survive contact with a production schema: a single mismatched terminal or missing via rule produces silent trace failures, orphaned features, and isolation traces that bleed across pressure or voltage boundaries during an outage. At the scale of a real distribution network, those defects are invisible until a field crew traces the wrong valve. This guide treats UN configuration as a reproducible, scriptable discipline and walks through schema initialization, connectivity and association rules, subnetwork tiers, and a copy-paste arcpy validation pipeline you can wire into a deployment gate.

This page sits under Understanding UN vs. Traditional GIS Networks, part of the Core Utility GIS Fundamentals & Network Models reference. If you have not yet internalized why the UN replaces implicit geometric snapping with explicit, rule-based topology, read that comparison first — every step below assumes the graph model rather than proximity-based connectivity.

Environment Prerequisites

Confirm the entire stack before touching the schema. Most “the trace returns nothing” tickets trace back to a prerequisite skipped here.

  • ArcGIS Pro 3.2+ (or ArcGIS Enterprise 11.2+ for a service-based deployment) with the Utility Network extension licensed and enabled for your account.
  • Geodatabase: an enterprise geodatabase (PostgreSQL, SQL Server, or Oracle) or a file geodatabase that supports UN schema version 5 or higher. Confirm with arcpy.Describe(gdb).release.
  • Spatial reference: aligned with your utility’s survey standard so coordinates resolve consistently during connectivity evaluation. Mismatches surface as spurious dirty areas — resolve them per CRS alignment & geodetic transformations before the network is created.
  • Feature dataset: a dedicated feature dataset is required; the UN cannot be created at the geodatabase root.
  • Python environment: the ArcGIS Pro conda environment with arcpy importable and initialized against the active project workspace so it inherits UN schema context.
  • Source data: asset feature classes staged and cleaned (no overlapping edges, no orphaned junctions) before they are added to the network — ideally through a governed data ingestion pipeline rather than ad-hoc imports.
ArcGIS Utility Network configuration pipeline A top-to-bottom dependency-ordered pipeline: cleaned source feature classes feed a dedicated feature dataset; the Utility Network capability is enabled; asset groups, asset types and terminal configurations are defined; connectivity and association rules are applied from version control; subnetwork tiers and controllers are configured; finally topology and subnetwork validation runs. A feedback arrow loops the validation step back to dirty-area resolution and the rule and terminal fixes before re-validating. STAGE 0 · INGEST Cleaned source feature classes no overlapping edges · no orphan junctions STEP 1 · CONTAINER Dedicated feature dataset aligned spatial reference · not at GDB root STEP 2 · ENABLE Create Utility Network capability arcpy.un.CreateUtilityNetwork() STEP 3 · ASSET MODEL Asset groups / types + terminals map terminals to the single-line diagram STEP 4 · RULES Connectivity & association rules applied from a version-controlled matrix STEP 5 · SUBNETWORKS Tiers & subnetwork controllers operational status sets trace boundaries STEP 6 · VALIDATE Topology + subnetwork validation ValidateTopology · ValidateSubnetwork dirty areas re-fix
Configuration runs strictly top-down in dependency order; any dirty areas surfaced by validation loop back to rule and terminal fixes before promotion.

Schema-Aware Validation Protocol (run this first)

Run these diagnostic checks before adding rules or building subnetworks. The most common configuration failure — terminal misalignment — is also the cheapest to catch here and the most expensive to catch in production, so it comes first.

  1. Verify terminal configurations against the single-line diagram. For every multi-port asset (transformers, regulators, switchgear), confirm each asset type’s terminal configuration maps terminal IDs directly to the manufacturer single-line diagram. Terminal misalignment is the primary vector for downstream trace anomalies; a transformer wired high-side to low-side will trace backwards silently.
  2. Inspect connectivity policy and association type. Use arcpy.Describe() on each candidate feature class to read its connectivityPolicy (EdgeJunction vs EdgeJunctionEdge) and confirm it matches the physical install standard — valves connect to mains, not directly to service lines.
  3. Audit asset group / asset type domain codes. Trace barriers and connectivity rules match on exact domain codes. Confirm every asset type code maps to a deterministic classification in your asset hierarchy so automated parsers and field crews resolve identifiers identically. Mismatched codes are the most common cause of silent trace bypasses.
  4. Clear existing dirty areas. Run arcpy.un.ValidateTopology(un_path) and inspect the resulting dirty areas. A network carrying stale dirty areas will return empty feature sets or raise execution errors regardless of how correct your new rules are.

A frequent failure surfacing during this phase is ERROR 003021 / ERROR 003022 — a missing or conflicting connectivity rule between two asset types. Resolve it by auditing the rule matrix for overlapping allow/prevent directives on the same asset pair and verifying terminal-to-terminal mappings against the engineering schematic. If traces terminate prematurely, check that edge-to-junction rules carry the correct via terminal constraints; ERROR 003025 indicates an implicit tier crossing that must be made explicit.

Connectivity, Association, and Subnetwork Configuration

With prerequisites verified, configure the schema in dependency order: asset model → connectivity rules → associations → subnetwork tiers.

Asset model. Enable the Utility Network capability on the feature dataset (UI: Geodatabase Administration pane; or arcpy.un.CreateUtilityNetwork()), then define asset groups and asset types that mirror your engineering standards and CMMS/ERP registries. Keep the schema definition in version control so it cannot drift between staging and production.

Connectivity rules. Explicitly define permissible connections between asset types, terminals, and edges in the Utility Network Properties → Connectivity Rules dialog, or via arcpy.un.AddConnectivityRule(). For repeatable deployments, export the rule matrix to CSV, version-control it, and apply it programmatically so every environment is built identically.

Associations. Structural associations (physical attachments) and containment associations (logical nesting — a substation containing transformers, a vault containing isolators) require separate configuration matrices. Get these right and attribute propagation and containment-aware traces follow naturally.

Subnetwork tiers and controllers. Configure domain networks first, then establish tiers (e.g., Transmission, Distribution, Medium Voltage, Low Voltage; or pressure zones for water) to segment trace evaluation. Designate subnetwork controllers — reclosers, breakers, transformers, or source valves — and populate their operational status fields. Misconfigured controller status is what causes isolation traces to bleed across intended boundaries and corrupt outage-management accuracy. Map subnetworkname and subnetworkcontroller to your SCADA/ADMS telemetry ingestion so the model and the operational picture stay in sync. The same controller-and-barrier logic underpins upstream and downstream tracing algorithms once the dataset is live.

Minimal Reproducible Implementation

The routine below is the validation core you should run after every schema change and before promoting a dataset. It clears and rebuilds dirty areas, validates subnetworks, scans returned geoprocessing messages for error signatures, and returns a structured result that a CI/CD gate can branch on. It handles geoprocessing exceptions explicitly rather than failing open.

import arcpy
import logging

logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")


def validate_un_dataset(un_path: str) -> dict:
    """Validate topology and subnetwork consistency for a Utility Network.

    Returns a structured dict suitable for CI/CD gating:
        {"valid": bool, "stage": str, "messages": str}
    """
    result = {"valid": False, "stage": "init", "messages": ""}
    try:
        # 1. Clear and rebuild dirty areas across the full extent.
        result["stage"] = "validate_topology"
        arcpy.un.ValidateTopology(un_path)
        logging.info("Topology validation complete.")

        # 2. Force a subnetwork rebuild and capture geoprocessing messages.
        result["stage"] = "validate_subnetwork"
        arcpy.un.ValidateSubnetwork(un_path)
        messages = arcpy.GetMessages()
        result["messages"] = messages

        # 3. Scan for error signatures the GP tools report without raising.
        lowered = messages.lower()
        if "error" in lowered or "failed" in lowered:
            logging.error("Subnetwork validation reported errors. "
                          "Inspect dirty areas and rule conflicts.")
            logging.error(messages)
            result["stage"] = "violations_detected"
            return result

        logging.info("UN dataset validated. No topology violations detected.")
        result["valid"] = True
        result["stage"] = "passed"
        return result

    except arcpy.ExecuteError:
        gp_messages = arcpy.GetMessages(2)
        logging.error("Geoprocessing failure: %s", gp_messages)
        result["messages"] = gp_messages
        result["stage"] += ":gp_error"
        return result
    except Exception as exc:  # defensive: never fail open in a deployment gate
        logging.exception("Unexpected validation failure.")
        result["messages"] = str(exc)
        result["stage"] += ":unexpected_error"
        return result


if __name__ == "__main__":
    outcome = validate_un_dataset(r"C:\data\utility.gdb\Utilities\ElectricNetwork")
    raise SystemExit(0 if outcome["valid"] else 1)

When a trace or validation does fail, follow this rapid resolution sequence:

  1. Isolate the failure scope. Run a targeted trace with include_barriers=True to find where the network graph terminates unexpectedly.
  2. Audit connectivity matrices. Cross-reference the failing asset pair against your version-controlled rule matrix for missing via mappings or conflicting allow/prevent directives.
  3. Rebuild the affected tier. Execute arcpy.un.UpdateSubnetwork() on that tier and watch the geodatabase transaction log for lock contention during enterprise deployments.
  4. Verify field mappings. Confirm lifecyclestatus, operationalstatus, and subnetworkcontroller are populated and match the domain network’s expected values — null status fields make isolation traces return empty.

Production Deployment Pattern

A compliant dataset is a living topology, not a one-time configuration. Promote it through a versioned, gated pipeline rather than editing production in place:

  • Versioned workspace. Apply schema and rule-matrix changes in an isolated branch version (or a staging geodatabase), validate, then reconcile and post. Keep the asset model, connectivity rules CSV, and terminal configurations in source control so any environment can be rebuilt deterministically with arcpy.un.AddConnectivityRule() and friends.
  • CI/CD gate. Run validate_un_dataset() under pytest on every schema pull request; its non-zero exit blocks the merge. Add a rule-matrix diff check and a terminal-configuration parity check across environments as additional gates. This mirrors the pattern in automating connectivity rule validation in CI pipelines.
  • CMMS/REST integration. Publish validated subnetworkname/subnetworkcontroller values to your CMMS and ADMS/SCADA ingestion so asset commissioning and retirement events stay synchronized with the live graph.
  • Retry/backoff. Enterprise validation contends with database locks; wrap ValidateSubnetwork/UpdateSubnetwork calls in bounded exponential backoff and surface lock-contention failures to the deployment log rather than silently retrying forever.

Conclusion

You now have a reproducible path to a production-grade Utility Network dataset: a verified environment, a diagnostic protocol that catches terminal and domain-code defects before they reach a trace, connectivity and association rules applied from version control, subnetwork tiers governed by explicit controllers, and an arcpy validation routine that gates promotion in CI/CD. Treating configuration this way eliminates the silent trace failures and boundary-bleed that undermine outage-management accuracy and audit-ready data lineage. The natural next step is to script the traces this schema enables — start with upstream and downstream tracing algorithms and the broader topology and tracing workflows reference.