Skip to content

Validation layers

Pacto validates contracts through four successive layers. Each layer short-circuits — if it fails, subsequent layers are skipped.

Layer 1: Structural (JSON Schema)

Validates against the embedded JSON Schema: - Field types match - Required fields are present - Enum values are valid - Conditional requirements are met (http needs port, etc.) - State invariants are enforced (stateless needs ephemeral)

Layer 2: Cross-field

Validates semantic references and consistency:

Rule Code
service.version is valid semver INVALID_SEMVER
Interface names are unique DUPLICATE_INTERFACE_NAME
Configuration names are unique DUPLICATE_CONFIGURATION_NAME
Policy names are unique DUPLICATE_POLICY_NAME
Dependency names are unique DUPLICATE_DEPENDENCY_NAME
http/grpc interfaces have port PORT_REQUIRED
event interfaces with port set PORT_IGNORED (warning)
grpc/event interfaces have contract CONTRACT_REQUIRED
health.interface matches a declared interface HEALTH_INTERFACE_NOT_FOUND
Health interface is not event type HEALTH_INTERFACE_INVALID
health.path required for http health interface HEALTH_PATH_REQUIRED
health.path on grpc health interface is ignored HEALTH_PATH_IGNORED (warning)
metrics.interface matches a declared interface METRICS_INTERFACE_NOT_FOUND
Metrics interface is not event type METRICS_INTERFACE_INVALID
metrics.path required for http metrics interface METRICS_PATH_REQUIRED
metrics.path on grpc metrics interface is ignored METRICS_PATH_IGNORED (warning)
Referenced files exist in the bundle FILE_NOT_FOUND
OCI dependency refs (oci://) are valid OCI references INVALID_OCI_REF
Compatibility ranges are valid semver constraints INVALID_COMPATIBILITY
Compatibility range is empty EMPTY_COMPATIBILITY
OCI dependency uses tag instead of digest TAG_NOT_DIGEST (warning)
image.ref is a valid OCI reference INVALID_IMAGE_REF
chart.ref (OCI) is a valid OCI reference INVALID_CHART_REF
chart.version is valid semver INVALID_CHART_VERSION
configurations[].ref is not a valid OCI reference INVALID_CONFIG_REF
configurations[].values without a schema VALUES_WITHOUT_SCHEMA
readiness.checks[].id are unique within the contract DUPLICATE_READINESS_ID
readiness.checks[].evidence is not blank/whitespace EMPTY_READINESS_EVIDENCE
readiness.checks[].description (when present) is not blank EMPTY_READINESS_DESCRIPTION
readiness.expires is a strict YYYY-MM-DD date INVALID_READINESS_EXPIRES
readiness.history[].{date,version,author,description} are valid/non-blank INVALID_READINESS_REVISION
configurations[].schema file is not valid JSON INVALID_CONFIG_JSON
configurations[].schema file is not valid JSON Schema INVALID_CONFIG_SCHEMA
configurations[].values don't match the schema CONFIG_VALUES_VALIDATION_FAILED
policies[].schema file does not exist in the bundle FILE_NOT_FOUND
policies[].schema file is not valid JSON INVALID_POLICY_JSON
policies[].schema file is not valid JSON Schema INVALID_POLICY_SCHEMA
policies[].ref is not a valid OCI reference INVALID_POLICY_REF
interfaces[].contract (YAML) file is not valid YAML INVALID_CONTRACT_FILE
scaling.min <= scaling.max SCALING_MIN_EXCEEDS_MAX
Job workloads cannot have scaling JOB_SCALING_NOT_ALLOWED
Stateless + persistent is invalid STATELESS_PERSISTENT_CONFLICT

Layer 3: Semantic

Validates cross-concern consistency:

Rule Code Type
ordered upgrade strategy with stateless state UPGRADE_STRATEGY_STATE_MISMATCH Warning

Layer 4: Policy enforcement

Resolves and enforces all declared policies against the contract. Policies are applied with strict AND semantics — the contract must satisfy every resolved policy. Contradictory policies naturally fail; no precedence or override logic is applied.

Condition Code
policies[].ref cannot be resolved (resolver unavailable, network error, bundle not found) POLICY_REF_UNRESOLVED
Cycle detected in recursive policy resolution chain POLICY_REF_CYCLE
Contract violates a policy constraint POLICY_VIOLATION
Contract YAML cannot be parsed for policy validation POLICY_ENFORCEMENT_ERROR

POLICY_REF_UNRESOLVED is a hard error — validation fails closed when a referenced policy cannot be resolved. This ensures that missing or unreachable policies are never silently skipped.

When ref-based policies are resolved. Recursive resolution of policies[].ref happens only when a resolver is configured. pacto validate and pacto push both supply one (they can reach OCI/file refs), so a ref policy that cannot be fetched fails closed with POLICY_REF_UNRESOLVED — this is how pacto push enforces remote policies before publishing. Local-only paths that pass no resolver — pacto pack and the operator — enforce only the locally-compiled schema-based policies and skip ref policies by design (they never reach the unresolved error). Cycle detection is per chain: a ref is a cycle only when it reappears in its own resolution chain (A → B → A); two sibling policies pointing at the same ref resolve independently.