Conformance codes
Every code conformance validation can raise - the full set validate_print() returns, and the set
dbprint check reports under conformance - sorted by code so one pasted from a failure can be
found. Data-quality assertions carry their own assertion.* codes, which are specified in
ASSERTIONS.md rather than here. This file is generated from the specification's
own catalog - do not edit it by hand. Run just docs to regenerate it.
A print conforms when no error is raised against it. A warning records an anomaly that does not
gate conformance; SPEC 6.1 defines both, and
SPEC 6.2 defines the issue each one is reported in.
135 codes: 107 error, 28 warning.
| Code | Severity | Specified in | Trigger |
|---|---|---|---|
annotations.claim-contradicts-statistic | warning | Annotations (§2.7) | A claims predicate (§2.7.1) evaluates against the column's own statistics.yaml and fails. WARNING - the axis is advisory (§2.4); a contradicted claim is never a gating defect |
annotations.claim-unassertable | warning | Annotations (§2.7) | A claims predicate cannot be evaluated: the stat is not in the assertion DSL's vocabulary, the predicate is malformed, the stat is not emitted for the column's classification, or the column is redacted |
annotations.grain-unknown-column | warning | Annotations (§2.7) | A grain.keys[] entry in statistics.annotations.yaml names a column not present in the table's statistics.yaml columns map (§2.7.1; stale key, not fatal) |
annotations.unknown-column | warning | Annotations (§2.7) | A key in statistics.annotations.yaml's columns map names a column not present in the table's statistics.yaml (stale key; not fatal) |
annotations.unknown-edge | warning | Annotations (§2.7) | A verdict in relationships.annotations.yaml addresses an edge absent from the table's own relationships.yaml refers_to (§2.7.2; stale, not fatal) |
annotations.unknown-value | warning | Annotations (§2.7) | A values entry in statistics.annotations.yaml names a value the column's own exhaustive values list does not have (§2.7.1; stale, not fatal - a truncated list is not checked) |
annotations.value-note-unassertable | warning | Annotations (§2.7) | A values entry addresses a column carrying a redacted marker (§2.2.9) - there is no literal to check the note against |
annotations.verdict-on-declared-edge | warning | Annotations (§2.7) | A verdict addresses an edge whose matching refers_to entry carries detection: declared (§2.7.2) - an annotation may correct an inference, never contradict a measurement (§2.4) |
ddl.empty-file | error | DDL (§2.1) | ddl.sql exists but is empty |
ddl.missing-trailing-newline | warning | DDL (§2.1) | File doesn't end with newline (POSIX convention; trivially auto-fixable) |
diff.comment-target-column-mismatch | error | Diff invariants (§2.6) | comment_changed with target=column missing column field, OR target=table with column field present |
diff.depends-on-changed-no-change | error | Diff invariants (§2.6) | depends_on_changed event's before and after are identical (§2.6.6) |
diff.grain-changed-no-change | error | Diff invariants (§2.6) | grain_changed event's before and after are identical (§2.6.6) |
diff.physical-layout-changed-no-change | error | Diff invariants (§2.6) | physical_layout_changed event's before and after are identical (§2.6.6) |
diff.relationship-modified-no-change | error | Diff invariants (§2.6) | relationship_modified event without on_delete OR on_update sub-objects (§2.6.6 rule) |
diff.row-count-changed-delta-mismatch | error | Diff invariants (§2.6) | table_row_count_changed where delta doesn't equal after - before |
diff.statistic-changed-delta-on-non-numeric | error | Diff invariants (§2.6) | statistic_changed with delta or delta_pct on stats where they MUST be omitted (distribution, classification, values) |
diff.statistic-changed-delta-pct-sign-mismatch | error | Diff invariants (§2.6) | statistic_changed where delta and delta_pct disagree in sign |
diff.summary-count-mismatch | warning | Diff invariants (§2.6) | Summary count doesn't match actual events count for that kind (informational redundancy; producer bug but not format break) |
diff.summary-total-mismatch | warning | Diff invariants (§2.6) | tables_modified + unchanged_tables + unevaluated_tables + tables_added doesn't equal target.tables_scanned (§2.6.4). WARNING on the same grounds as diff.summary-count-mismatch: the events remain readable, and every operand is redundant with them |
layout.invalid-path-segment | error | Directory layout (§1) | Path segment fails the §1.5.1 allowlist regex |
layout.missing-diff | error | Directory layout (§1) | Connection root missing diff.yaml though manifest.yaml records a table (§1.2) |
layout.missing-manifest | error | Directory layout (§1) | Connection root missing manifest.yaml |
layout.missing-reading-guide | error | Directory layout (§1) | Connection root missing reading.md (§1.2) |
layout.unexpected-directory-level | error | Directory layout (§1) | Extra directory between connection root and per-table dir (depth mismatch per adapter hierarchy) |
layout.unknown-file | warning | Directory layout (§1) | File inside per-table dir not in the canonical artifact list (extensibility tolerance) |
manifest.columns-count-mismatch | error | Manifest cross-checks (§2.5) | A table entry's columns count disagrees with the size of its statistics.yaml columns map (§2.5) |
manifest.missing-artifact | error | Manifest cross-checks (§2.5) | Manifest entry references file that doesn't exist on disk |
manifest.orphaned-artifact | warning | Manifest cross-checks (§2.5) | File on disk not listed in any manifest entry (could be in-progress write; not strictly a violation) |
manifest.selectors-mismatch-diff | error | Manifest cross-checks (§2.5) | selectors disagrees with diff.yaml's target.selectors when both are present (§2.5, §2.6.3) |
manifest.table-fqn-mismatch | error | Manifest cross-checks (§2.5) | Manifest's table FQN doesn't match the table field in the referenced statistics.yaml / relationships.yaml |
privacy.redacted-value-compared | error | Privacy (§4.4) | diff.yaml carries a statistic_changed event for values, range, percentiles, mean, sum or length on a column whose statistics.yaml declares a redacted marker (§2.6.6). ERROR, not WARNING: the marker is a producer's own declaration, so no inference is being second-guessed |
privacy.unredacted-sensitive | warning | Privacy (§4.4) | Column carries inferred.sensitivity and publishes at least one of values, range, percentiles, with no redacted primitive covering it (§4.4.2) |
relationships.broken-reciprocity | error | Relationships invariants (§2.3) | A referenced_by entry points to a source table that's in the manifest BUT lacks the matching refers_to entry |
relationships.column-array-length-mismatch | error | Relationships invariants (§2.3) | column and target_column (in refers_to) or column and referencer_column (in referenced_by) have different array lengths |
relationships.ineligible-target-is-referenced | error | Relationships invariants (§2.3) | eligible_target: false but referenced_by carries an inferred entry - naming inference cannot resolve an edge to an ineligible object (§2.3.8). A declared entry there is unaffected; a composite key inference never reaches can still be a real FK target |
relationships.observed-answerable-count-mismatch | error | Relationships invariants (§2.3) | observed.answerable_count disagrees with the count of the referencing column's own retained hashes below the shared threshold (§2.3.10, §2.2.14), including when the answerable subset is empty and no count should be published at all |
relationships.observed-coherent-mismatch | error | Relationships invariants (§2.3) | observed.coherent disagrees with whether the referencing column's cardinality exceeds the referenced column's (§2.3.10) |
relationships.observed-containment-forbidden | error | Relationships invariants (§2.3) | observed.containment is published where the two endpoints' sketches carry no evidence to support it - the answerable subset between them is empty (§2.3.10) |
relationships.observed-containment-mismatch | error | Relationships invariants (§2.3) | observed.containment disagrees with the bottom-k intersection estimate recomputed from the two endpoints' own sketch (§2.3.10, §2.2.14) |
relationships.observed-coverage-mismatch | error | Relationships invariants (§2.3) | observed.target_coverage disagrees with the two endpoints' own cardinality / cardinality, rounded per §2.2.6 (§2.3.10) |
relationships.observed-fanout-mismatch | error | Relationships invariants (§2.3) | observed.fanout_avg disagrees with the referencing column's own row_count / cardinality, rounded per §2.2.6 (§2.3.10) |
relationships.path-on-composite-endpoint | error | Relationships invariants (§2.3) | path (or target_path) is present but its partner array (column or target_column) names more than one column (§2.3.9) - a path endpoint is representable only on a single-column endpoint |
schema.invalid-percentile-key | error | YAML / schema validity (§§2.2–2.6) | Percentile key doesn't match ^p\d{2}$ |
schema.invalid-yaml | error | YAML / schema validity (§§2.2–2.6) | File isn't valid YAML |
schema.missing-required-field | error | YAML / schema validity (§§2.2–2.6) | Required field absent per JSON Schema |
schema.type-mismatch | error | YAML / schema validity (§§2.2–2.6) | Field has wrong scalar type |
schema.unknown-change-kind | warning | YAML / schema validity (§§2.2–2.6) | kind value in diff not in the enum (forward-compat) |
schema.unknown-classification | warning | YAML / schema validity (§§2.2–2.6) | classification value not in the enum (forward-compat) |
schema.unknown-epoch-unit | warning | YAML / schema validity (§§2.2–2.6) | inferred.epoch_unit value not in the enum (forward-compat) |
schema.unknown-looks-like | warning | YAML / schema validity (§§2.2–2.6) | inferred.looks_like value not in the enum (forward-compat) |
schema.unknown-sensitivity | warning | YAML / schema validity (§§2.2–2.6) | inferred.sensitivity value not in the enum (forward-compat) |
stats.candidate-key-exception-mismatch | error | Statistics invariants (§2.2) | inferred.candidate_key_exception disagrees with the value recomputed from cardinality, cardinality_ratio, cardinality_method and null_count (§4.2) |
stats.candidate-key-mismatch | error | Statistics invariants (§2.2) | inferred.candidate_key disagrees with whether cardinality_ratio clears the SPEC 4.2 threshold - present where it should be absent, or the reverse. Independent of classification |
stats.cardinality-exceeds-row-count | error | Statistics invariants (§2.2) | cardinality > row_count (invariant violation) |
stats.cardinality-ratio-mismatch | error | Statistics invariants (§2.2) | cardinality_ratio disagrees with cardinality / rows_scanned, rounded per §2.2.6 |
stats.degenerate-count-exceeds-row-count | error | Statistics invariants (§2.2) | zero_count, negative_count, empty_count or quantized_count exceeds the non-null scanned count (invariant violation) |
stats.dependencies-direction-impossible | error | Statistics invariants (§2.2) | A dependencies entry's determinant has lower cardinality than its dependent - a function's image cannot exceed its domain, so that direction cannot hold (§2.2.13) |
stats.dependencies-measured-on-empty-table | error | Statistics invariants (§2.2) | dependencies is non-empty on a table with row_count: 0 - every combination is trivially functional there (§2.2.13) |
stats.dependencies-measured-under-scope | error | Statistics invariants (§2.2) | dependencies is non-empty on a file that also carries scope - a dependency measured over a sample is not a dependency (§2.2.13) |
stats.dependencies-self-referential | error | Statistics invariants (§2.2) | A dependencies entry's determinant and dependent name the same column (§2.2.13) |
stats.dependencies-strength-out-of-range | error | Statistics invariants (§2.2) | A dependencies entry's strength is not in (0, 1] (§2.2.13) |
stats.dependencies-unknown-column | error | Statistics invariants (§2.2) | A dependencies entry names a determinant or dependent absent from the file's columns map (§2.2.13) |
stats.depends-on-on-table | error | Statistics invariants (§2.2) | depends_on is present but type is table - the field names what a view/matview reads and MUST NOT appear on a plain table (§2.2.17) |
stats.distribution-contradicts-frequencies | error | Statistics invariants (§2.2) | On a numeric/temporal column with cardinality_method: exact, distribution disagrees with the verdict recomputed from frequencies (§2.2.5). ERROR because the two come from the same fetch and are exact arithmetic, not a heuristic over a possibly-truncated list |
stats.distribution-mismatch | warning | Statistics invariants (§2.2) | When verifiable from an exhaustive values list, distribution value doesn't match §2.2.5 rules. WARNING because heuristic-prone for truncated lists and exact-match boundaries. |
stats.excess-precision | error | Statistics invariants (§2.2) | A numeric statistic carries more than 6 decimal places (§2.2.6) |
stats.forbidden-field-for-classification | error | Statistics invariants (§2.2) | Column has a field marked — in the §2.2.3 matrix |
stats.grain-duplicate-key | error | Statistics invariants (§2.2) | The same column combination appears in more than one grain.keys entry (§2.2.12) |
stats.grain-measured-on-empty-table | error | Statistics invariants (§2.2) | grain.keys carries a detection: measured entry on a table with row_count: 0 - every combination is trivially unique there (§2.2.12) |
stats.grain-measured-under-scope | error | Statistics invariants (§2.2) | grain.keys carries a detection: measured entry on a file that also carries scope - uniqueness over a sample is not uniqueness (§2.2.12) |
stats.grain-unknown-column | error | Statistics invariants (§2.2) | A grain.keys entry names a column absent from the file's columns map (§2.2.12) |
stats.length-order-violated | error | Statistics invariants (§2.2) | length.min, length.avg and length.max disagree with min <= avg <= max (§2.2.4) |
stats.looks-like-candidate-at-verdict-threshold | error | Statistics invariants (§2.2) | inferred.looks_like_candidate_share is at or above the 95% verdict threshold - a share that high would have been inferred.looks_like instead (§4.1.3) |
stats.looks-like-candidate-with-verdict | error | Statistics invariants (§2.2) | inferred.looks_like_candidate is present alongside inferred.looks_like; the near-miss and the verdict are mutually exclusive (§4.1.3) |
stats.max-age-days-mismatch | error | Statistics invariants (§2.2) | freshness.max_age_days disagrees with max(0, day_count(range.max, profiled_at)) (§2.2.4). Skipped when the column carries any redacted marker, max is named in unrepresentable, or range.max is not a parseable instant |
stats.mean-outside-range | error | Statistics invariants (§2.2) | mean lies outside [range.min, range.max] (§2.2.4). An average outside its own bounds is impossible over any nonempty column, so it reports a producer that lost the magnitude of one of the three |
stats.measurement-under-catalog-only | error | Statistics invariants (§2.2) | A column carries a field beyond sql_type, nullable, classification, physical_name, collation, physical_layout_key on a file that also carries catalog_only - a measurement published where none was queried (§2.2.15) |
stats.missing-required-field-for-classification | error | Statistics invariants (§2.2) | Column missing a field marked R in the §2.2.3 matrix for its classification |
stats.normalized-cardinality-exceeds-cardinality | error | Statistics invariants (§2.2) | normalized_cardinality exceeds cardinality; folding case and trimming whitespace cannot increase distinctness (§2.2.4). Not checked when cardinality_method is approximate - the comparison is approximate on both sides there |
stats.null-count-exceeds-row-count | error | Statistics invariants (§2.2) | null_count > row_count (invariant violation) |
stats.null-patterns-absent-with-nulls | error | Statistics invariants (§2.2) | null_patterns is omitted although some column reports a non-zero null_count and the file's own unmeasured list does not name it, or present although no column reports one (§2.2.10) |
stats.null-patterns-coverage-mismatch | error | Statistics invariants (§2.2) | null_patterns.coverage disagrees with the listed counts over rows_scanned (§2.2.10) |
stats.null-patterns-duplicate-combination | error | Statistics invariants (§2.2) | The same combination of columns appears in more than one null_patterns entry (§2.2.10) |
stats.null-patterns-not-ordered | error | Statistics invariants (§2.2) | null_patterns.patterns is not ordered by count descending, ties by ascending columns (§2.2.10) |
stats.null-patterns-reconciliation-mismatch | error | Statistics invariants (§2.2) | The null_patterns counts naming a column exceed its null_count, or fall short of it at coverage: 1.0 (§2.2.10), coverage_method absent or measured. coverage_method: bounded reports stats.null-patterns-reconciliation-mismatch-bounded instead - see below |
stats.null-patterns-reconciliation-mismatch-bounded | warning | Statistics invariants (§2.2) | The same disagreement as stats.null-patterns-reconciliation-mismatch, where coverage_method: bounded (§2.2.10) already discloses the cause. WARNING for the same reason |
stats.null-patterns-sum-exceeds-rows-scanned | error | Statistics invariants (§2.2) | The null_patterns counts sum to more rows than were scanned (§2.2.10), coverage_method absent or measured. coverage_method: bounded reports stats.null-patterns-sum-exceeds-rows-scanned-bounded instead - see below |
stats.null-patterns-sum-exceeds-rows-scanned-bounded | warning | Statistics invariants (§2.2) | The same disagreement as stats.null-patterns-sum-exceeds-rows-scanned, where coverage_method: bounded (§2.2.10) already discloses that the census and rows_scanned were not read at the same instant. WARNING because the producer has already named the cause this error exists to catch |
stats.null-patterns-unknown-column | error | Statistics invariants (§2.2) | A null_patterns entry names a column absent from the file's columns map (§2.2.10) |
stats.null-rate-mismatch | error | Statistics invariants (§2.2) | null_rate disagrees with null_count / rows_scanned, rounded per §2.2.6 |
stats.nullable-contradicts-null-count | error | Statistics invariants (§2.2) | nullable: false alongside a nonzero null_count - nullable is a DDL fact (§2.2.2), never a data measurement, so it cannot disagree with a NULL the column's own scan found |
stats.percentile-outside-range | error | Statistics invariants (§2.2) | A percentile lies outside [range.min, range.max] (§2.2.4). range and percentiles are read by one statement per column, so this does not carry the cross-phase tolerance stats.values-sum-mismatch does. Skipped when the column carries any redacted marker |
stats.percentiles-not-ordered | error | Statistics invariants (§2.2) | percentiles do not ascend with their keys (§2.2.4). Compares parsed values, not key spelling; a value that cannot be read back (unrepresentable, unparseable) is skipped rather than failing the column |
stats.physical-layout-key-missing-marker | error | Statistics invariants (§2.2) | physical_layout.keys names a column that does not carry physical_layout_key: true (§2.2.11) |
stats.physical-layout-key-not-declared | error | Statistics invariants (§2.2) | A column carries physical_layout_key: true but is not named in physical_layout.keys (§2.2.11) |
stats.physical-layout-unknown-column | error | Statistics invariants (§2.2) | physical_layout.keys names a column absent from the file's columns map (§2.2.11) |
stats.physical-name-matches-key | warning | Statistics invariants (§2.2) | physical_name is present and equals the column's own map key; the field asserts nothing and MUST be omitted (§2.2.4) |
stats.populated-out-of-anchor-range | error | Statistics invariants (§2.2) | populated.from or populated.to falls outside the anchor column's own measured range (§2.2.4) |
stats.populated-without-timeline | error | Statistics invariants (§2.2) | A column carries populated on a file with no timeline block - there is nowhere to read the anchor its instants are dated against (§2.2.4, §2.2.16) |
stats.population-marker-mismatch | error | Statistics invariants (§2.2) | A column's rows_scanned disagrees with what the file's scope requires - absent or wrong when scoped, present when not (§2.2.8) |
stats.redacted-without-marker | error | Statistics invariants (§2.2) | A values entry carries no value but the column declares no redacted primitive (§2.2.9) |
stats.scope-asserts-nothing | warning | Statistics invariants (§2.2) | scope covers the whole table and records neither sample nor filter; omit it |
stats.scope-missing-rows-scanned | error | Statistics invariants (§2.2) | scope is present without an integer rows_scanned (§2.2.8) |
stats.scope-not-a-mapping | error | Statistics invariants (§2.2) | scope is present but is not a mapping (§2.2.8) |
stats.scope-rows-scanned-exceeds-row-count | error | Statistics invariants (§2.2) | scope.rows_scanned > row_count while row_count_method is exact — a subset cannot be larger than the set it was drawn from. Permitted under approximate, which is the estimate-undershot case §2.2.8 sanctions |
stats.scope-sample-and-filter | error | Statistics invariants (§2.2) | scope carries both sample and filter — a table is narrowed one way or the other (§2.2.8) |
stats.scope-sample-out-of-range | error | Statistics invariants (§2.2) | scope.sample outside the interval (0, 1] |
stats.sketch-invalid-encoding | error | Statistics invariants (§2.2) | sketch.values is not valid base64 of a length that is a multiple of 8 bytes (§2.2.14) |
stats.sketch-not-ascending | error | Statistics invariants (§2.2) | A decoded sketch.values is not sorted ascending (§2.2.14) |
stats.sketch-oversized | error | Statistics invariants (§2.2) | A decoded sketch.values carries more entries than method's own k (§2.2.14) |
stats.sketch-unknown-method | error | Statistics invariants (§2.2) | sketch.method is not a value this MAJOR defines (§2.2.14) |
stats.span-days-mismatch | error | Statistics invariants (§2.2) | range.span_days disagrees with day_count(range.min, range.max) (§2.2.4). Skipped when either bound is redacted (mask/hash), named in unrepresentable, or not a parseable ISO date/instant |
stats.timeline-anchor-not-temporal | error | Statistics invariants (§2.2) | timeline.column names a column whose classification is not temporal (§2.2.16) |
stats.timeline-anchor-redacted | error | Statistics invariants (§2.2) | timeline.column names a column carrying a redacted marker - the anchor rule MUST NOT choose a redacted column (§2.2.16) |
stats.timeline-buckets-unordered | error | Statistics invariants (§2.2) | timeline.buckets is not ascending by start (§2.2.16) |
stats.timeline-coverage-mismatch | error | Statistics invariants (§2.2) | timeline.coverage disagrees with the listed bucket counts over rows_scanned (§2.2.16) |
stats.timeline-on-empty-table | error | Statistics invariants (§2.2) | timeline is present on a table with row_count: 0 - there is nothing to bucket (§2.2.16) |
stats.timeline-under-scope | error | Statistics invariants (§2.2) | timeline is present on a file that also carries scope - a bucketed count over a sample is not a timeline (§2.2.16) |
stats.timeline-unknown-column | error | Statistics invariants (§2.2) | timeline.column names a column absent from the file's columns map (§2.2.16) |
stats.uncoarsened-redacted-day-count | error | Statistics invariants (§2.2) | A temporal column carrying a redacted marker emits freshness.max_age_days or range.span_days not floored to a multiple of 90 (§2.2.9) |
stats.unmeasured-names-emitted-block | error | Statistics invariants (§2.2) | the file's unmeasured list names a table-level block the same file also emits (§2.2.1) |
stats.unmeasured-names-emitted-field | error | Statistics invariants (§2.2) | unmeasured names a field the same column also emits - a measurement and its own absence cannot both be claimed (§2.2.4) |
stats.unmeasured-names-unrequired-field | error | Statistics invariants (§2.2) | unmeasured names a field the §2.2.3 matrix does not mark R for this column's classification; that absence is structural and needs no marker (§2.2.4) |
stats.unrepresentable-empty | error | Statistics invariants (§2.2) | unrepresentable is present as an empty list; the key MUST be omitted instead (§2.2.4) |
stats.unrepresentable-names-unemitted-field | error | Statistics invariants (§2.2) | unrepresentable names a field (min, max, or a percentiles key) the column did not emit (§2.2.4) |
stats.values-coverage-mismatch | warning | Statistics invariants (§2.2) | values_coverage disagrees with the listed counts over rows_scanned - null_count. WARNING for the same cross-phase reason as stats.values-sum-mismatch: the two ratios share the same listed/non_null pair, and a drift small enough to still disagree at six decimals is the same drift, not a distinct producer defect |
stats.values-list-exceeds-cardinality | warning | Statistics invariants (§2.2) | An exhaustive values list carries more entries than cardinality, cardinality_method: exact. WARNING for the same cross-phase reason as stats.values-sum-mismatch |
stats.values-list-short-of-cardinality | error | Statistics invariants (§2.2) | An exhaustive values list (values_coverage of 1.0, values_coverage_method absent or measured) carries fewer entries than cardinality, cardinality_method: exact (§2.2.4). ERROR because values_coverage and cardinality are both required exact fields whenever this fires - a live table taking writes between the two phases can widen cardinality past a list that was already complete when it was read, which is the phase A / phase B disagreement stats.values-sum-mismatch's neighbors tolerate at warning; this code's own severity is unchanged. values_coverage_method: bounded reports stats.values-list-short-of-cardinality-bounded instead - see below |
stats.values-list-short-of-cardinality-bounded | warning | Statistics invariants (§2.2) | The same disagreement as stats.values-list-short-of-cardinality, where values_coverage_method: bounded (§2.2.4) already discloses that values_coverage is a clamp, not a measurement read at the same instant as cardinality. WARNING because the producer has already named the cause this error exists to catch |
stats.values-not-ordered | error | Statistics invariants (§2.2) | values entries are not ordered by count DESC with a lexicographic tie-break (§2.2.4) |
stats.values-sum-mismatch | warning | Statistics invariants (§2.2) | An exhaustive values list (values_coverage of 1.0) whose counts do not sum to rows_scanned - null_count, OR a truncated list whose counts exceed it. WARNING because phase A and phase B are measured in separate statements against a table taking writes - on a live database the two counts can disagree by design, not by producer defect |
version.invalid-format-version | error | Format version (§5) | format_version isn't a positive integer |
version.missing-format-version | error | Format version (§5) | Required artifact missing format_version field |
version.unknown-format-version | error | Format version (§5) | format_version is a MAJOR the v1 validator doesn't understand (e.g., 2) — the validator's job is to validate v1; cannot do so for unknown majors |