#[non_exhaustive]pub enum Reason {
Show 50 variants
MissingSymbol {
symbol: SymbolRef,
first_seen_at_tag: Option<TagName>,
needs_pin_at_least: Option<NeedsPin>,
suggested_replacement: Option<SymbolRef>,
},
ArityChanged {
module: ModuleName,
function: FunctionName,
expected: Arity,
found: Vec<Arity>,
expected_available_at: Option<TagName>,
needs_pin_at_least: Option<NeedsPin>,
},
SignatureChanged {
module: ModuleName,
function: FunctionName,
arity: Arity,
expected_spec: String,
found_spec: String,
},
FileAbsent {
path: PathBuf,
},
ContextDrift {
path: PathBuf,
hunk_index: usize,
},
PreimageDrifted {
path: PathBuf,
hunk_index: usize,
line_delta: isize,
},
PostimageCollision {
path: PathBuf,
hunk_index: usize,
},
PreimageMissing {
path: PathBuf,
hunk_index: usize,
preimage_excerpt: String,
},
DeprecatedUsage {
symbol: SymbolRef,
since: Option<TagName>,
replacement: Option<SymbolRef>,
},
NowHidden {
module: ModuleName,
},
RecordFieldsChanged {
record: RecordName,
expected: Vec<FieldName>,
found: Vec<FieldName>,
},
UnsupportedFileType {
path: PathBuf,
},
UntrackedModuleMissing {
module: ModuleName,
},
ClauseMismatch {
module: ModuleName,
function: FunctionName,
arity: Arity,
call_args: Vec<ArgShape>,
pin_clauses: Vec<Vec<ArgShape>>,
},
MissingPrereq {
symbol: SymbolRef,
self_branch: GitRef,
suggested_source_for_prereq: Option<CommitSha>,
},
SyntacticArtifact {
path: PathBuf,
line: usize,
artifact: ArtifactKind,
},
BehaviourCallbackSignatureChanged {
behaviour: ModuleName,
callback: FunctionName,
arity: Arity,
expected_after_patch: String,
implementer: ModuleName,
implementer_signature: String,
},
BehaviourCallbackRemoved {
behaviour: ModuleName,
callback: FunctionName,
arity: Arity,
implementer: ModuleName,
},
BehaviourCallbackAdded {
behaviour: ModuleName,
callback: FunctionName,
arity: Arity,
implementer: ModuleName,
},
ModuleRelocated {
module: ModuleName,
patch_path: PathBuf,
},
WireConstantChanged {
module: ModuleName,
macro_name: String,
before: String,
after: String,
},
HistoricalImplementationMissing {
module: ModuleName,
advertised_version_before: u32,
advertised_version_after: u32,
expected_historical_module: ModuleName,
},
WireContractBodyDrift {
module: ModuleName,
functions: Vec<FunctionName>,
advertised_version: u32,
},
WireContractRegression {
module: ModuleName,
pin_version: u32,
patch_version: u32,
},
ReturnShapeMismatch {
module: ModuleName,
function: FunctionName,
arity: Arity,
source_signature: String,
pin_signature: String,
},
MissingType {
module: ModuleName,
name: TypeName,
arity: Arity,
},
PathRename {
source_path: PathBuf,
target_path: PathBuf,
translation: TranslationSource,
},
TargetPathAbsent {
path: RelativePath,
},
TestModuleSymbolMissing {
suite_path: RelativePath,
missing_module: ModuleName,
call_sites: Vec<TestCallSite>,
},
BehaviourModuleMissing {
source_path: RelativePath,
behaviour: ModuleName,
},
HeaderFileMissing {
source_path: RelativePath,
include_directive: IncludeDirective,
attempted_paths: Vec<RelativePath>,
},
MacroUndefinedOnTarget {
source_path: RelativePath,
macro_name: String,
line: u32,
},
RecordUndefinedOnTarget {
source_path: RelativePath,
record_name: RecordName,
line: u32,
},
LocalCallUndefinedOnTarget {
source_path: RelativePath,
function: FunctionName,
arity: Arity,
line: u32,
},
QualifiedCallUndefinedOnTarget {
source_path: RelativePath,
module: ModuleName,
function: FunctionName,
arity: Arity,
line: u32,
},
QualifiedCallReturnShapeDrift {
source_path: RelativePath,
module: ModuleName,
function: FunctionName,
arity: Arity,
source_signature: String,
target_signature: String,
line: u32,
},
LocalCallReturnShapeDrift {
source_path: RelativePath,
function: FunctionName,
arity: Arity,
source_signature: String,
target_signature: String,
line: u32,
},
MacroValueDrift {
source_path: RelativePath,
macro_name: String,
source_value: String,
target_value: String,
line: u32,
},
BehaviourCallbackAddedOnTarget {
source_path: RelativePath,
behaviour: ModuleName,
callback: FunctionName,
arity: Arity,
line: u32,
},
BehaviourCallbackDriftOnTarget {
source_path: RelativePath,
behaviour: ModuleName,
callback: FunctionName,
arity: Arity,
source_signature: String,
target_signature: String,
line: u32,
},
VersionedMachineSnapshotMissing {
module: ModuleName,
side: SnapshotSide,
},
WireConstantBindingsMissing {
module: ModuleName,
macros: Vec<MacroName>,
side: SnapshotSide,
},
IndirectCallUndefinedOnTarget {
source_path: RelativePath,
module: ModuleName,
function: FunctionName,
arity: Arity,
via: IndirectCallForm,
line: u32,
},
ExportedTypeUndefinedOnTarget {
source_path: RelativePath,
type_name: TypeName,
arity: Arity,
line: u32,
},
BehaviourCallbackUnknownOnPin {
behaviour: ModuleName,
callback: FunctionName,
arity: Arity,
pin_arities: Vec<Arity>,
implementer: ModuleName,
evidence: DriftEvidence,
},
BehaviourCallbackMissingOnPin {
behaviour: ModuleName,
callback: FunctionName,
arity: Arity,
implementer: ModuleName,
},
OptionKeyUnknownOnPin {
project: ProjectName,
module: ModuleName,
type_name: TypeName,
key: MapKey,
pin_tag: TagName,
},
SuiteNotRegisteredForCt {
suite_path: RelativePath,
makefile_path: RelativePath,
},
SchemaFeatureUnsupportedOnPin {
schema_path: RelativePath,
conf_key: Option<String>,
feature: SchemaFeature,
required_version: String,
pinned_version: String,
},
SchemaKeyReaderMissing {
schema_path: RelativePath,
target_key: String,
searched_apps: Vec<ApplicationName>,
absent_apps: Vec<ApplicationName>,
},
}Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
MissingSymbol
Fields
ArityChanged
Fields
module: ModuleNamefunction: FunctionNameSignatureChanged
FileAbsent
ContextDrift
PreimageDrifted
The contiguous preimage block (Context and Removed lines from
the hunk) was found verbatim at a different starting line.
Cherry-pick adapters handle this with the -x trailer; the
operator just needs the delta to confirm the patch’s intent
still applies.
PostimageCollision
The hunk’s preimage matches, but its added lines land at a file edge where the target already has divergent content the base lacked: an add/add a contiguous preimage match cannot detect. The 3-way cherry-pick conflicts where the preimage-only check reads clean. Non-blocking: the operator resolves the overlap.
PreimageMissing
The preimage block does not appear anywhere in the file. The patch was authored against a tree where the lines existed; on this pin they don’t. Structurally inapplicable: the operator needs an excerpt to reason about why.
DeprecatedUsage
NowHidden
Fields
module: ModuleNameRecordFieldsChanged
UnsupportedFileType
UntrackedModuleMissing
Fields
module: ModuleNameClauseMismatch
Call-site argument shapes don’t satisfy any clause head at the
pin. Emitted when both the call and the pin’s clause patterns
are concrete enough to compare; Unknown on either side
suppresses the reason.
MissingPrereq
Patch references an MFA owned by the self-project but absent from the
resolved self-snapshot. suggested_source_for_prereq is filled only
with --suggest-prereqs.
SyntacticArtifact
Pre-flight syntactic damage in a touched file: an unresolved merge-conflict marker, an exported function with no definition, etc.
BehaviourCallbackSignatureChanged
Patch changes a -callback signature; an implementer still has the old one.
BehaviourCallbackRemoved
Patch removes a required callback; implementer still exports it.
BehaviourCallbackAdded
Patch adds a required callback; implementer is missing the export.
ModuleRelocated
Patch touches a path absent on pin, but a module of the same basename exists elsewhere.
WireConstantChanged
Wire-bearing macro value differs between source and pin.
HistoricalImplementationMissing
version/0 advanced without the matching historical-implementation module.
WireContractBodyDrift
Function bodies drifted at the same advertised version/0. Mixed-version cluster risk.
WireContractRegression
version/0 decreased pin → patch.
ReturnShapeMismatch
Spec return shape differs between source and pin for a referenced MFA.
MissingType
A type-reference inside a -spec, -callback, -type, or
-opaque attribute resolves to a name and arity that the pin
does not expose via -export_type. Non-blocking: a missing
type alias is a dialyzer-level concern, not a load-time crash.
PathRename
A touched path is absent from the target tree, but a
configured [[path_translation]] rewrites it to a path that
does exist on the target. Non-blocking: the operator (or the
cherry-pick driver) rewrites the path before applying.
TargetPathAbsent
A touched path is absent on the target while others are present
and no [[path_translation]] rewrites it. Non-blocking: dropping
the hunks for this path lets the rest apply. The all-absent case
is InapplicableReason::PathsMissingOnTarget.
Fields
path: RelativePathTestModuleSymbolMissing
A _SUITE.erl file in the patch references missing_module:f/n
where missing_module resolves to no source file under any
configured FamilyDefaults.test_helper_search_paths on the
target tree. The cherry-pick compiles and the SUITE may even
load, but every call to the missing helper crashes at runtime:
the failure pattern seen in the Jun 2026 v4.1.x → v4.0.x round
(the amqp_utils:connection_config/1 undef in
amqp10_connection_max_SUITE). Non-blocking by default: the
diagnostic equivalent (Diagnostics.missing_test_modules)
always fires; the Reason variant fires only when
--target-repo-dir-path is supplied and the resolution is
authoritative.
BehaviourModuleMissing
A touched .erl declares -behaviour(behaviour) (or
-behavior(...)) where behaviour resolves to no source
module on the target tree. erlc compiles with a warning,
then hook dispatch crashes at runtime. The BehaviourCallback*
variants model implementer drift; this one catches the
missing-behaviour-module case they do not.
HeaderFileMissing
A touched .erl or .hrl declares -include(path) or
-include_lib(app/include/file.hrl) against a target tree that
does not ship the resolved header. Compile-time failure rather
than runtime, but same user-facing shape as
TestModuleSymbolMissing: looked fine on source, broken on
target.
Fields
source_path: RelativePathinclude_directive: IncludeDirectiveattempted_paths: Vec<RelativePath>MacroUndefinedOnTarget
A touched .erl or .hrl file references ?MACRO on an added
line, but MACRO is defined nowhere the target tree reaches (not
in the file, its includes, or the patch itself) and is not
predefined. Compiles on source, dangles on target. Non-blocking:
the operator drops or adapts the reference.
RecordUndefinedOnTarget
A touched .erl or .hrl file uses #record{} on an added
line, but record is defined nowhere the target tree reaches and
is not added by the patch. Same check as MacroUndefinedOnTarget
for the record namespace; non-blocking.
LocalCallUndefinedOnTarget
A touched .erl file calls an unqualified f/a on an added line
that the target version of the same module neither defines,
exports, imports, nor inherits as an auto-imported BIF. The
same check for the function namespace; non-blocking.
QualifiedCallUndefinedOnTarget
A touched .erl file calls a qualified m:f/a on an added line
whose module is a first-party module present on the target tree,
but the target version of that module does not export f/a (and
the patch does not add it). The qualified form of
LocalCallUndefinedOnTarget, resolved against the called
module’s exports. Withheld when any pin snapshot already covers
the module, when it is absent from the tree, or when its export
surface is not fully readable. Non-blocking.
QualifiedCallReturnShapeDrift
A qualified m:f/a call that resolves against the target tree
has a target-tree -spec return shape that disagrees with its
source-tree -spec. Same comparison as ReturnShapeMismatch on
the live, snapshot-free first-party axis: same comparator,
non-blocking like the rest of that axis. Only evaluated once the
call is confirmed to resolve; withheld when either side lacks a
-spec.
LocalCallReturnShapeDrift
An unqualified call that resolves against the target module’s
own definitions has a target-tree -spec return shape that
disagrees with its source-tree -spec. The local-call form of
QualifiedCallReturnShapeDrift; imported resolutions are
withheld, since the callee’s spec is in another module.
MacroValueDrift
A ?MACRO the patch uses is defined in the touched file itself
on both trees, exactly once each, and the normalized -define
bodies disagree: the compile-clean, behavior-divergent class.
Withheld for definitions reached any other way. Non-blocking.
Fields
source_path: RelativePathBehaviourCallbackAddedOnTarget
The target’s version of a behaviour the patch declares requires
a callback the source’s version does not, and the target does
not list it as optional: an implementation written against the
source is missing it. line is the -behaviour attribute’s
line in the touched file. Non-blocking.
BehaviourCallbackDriftOnTarget
A callback both trees’ versions of a declared behaviour declare has a different normalized signature on the target. The whole signature is compared, not just the return half: a callback contract’s argument types are the implementer’s obligation. Non-blocking.
VersionedMachineSnapshotMissing
Declared versioned-machine module is touched but the snapshot
has no recorded versioned_machine_version on side.
Non-blocking.
WireConstantBindingsMissing
Declared wire constants are touched but the snapshot’s
wire_constants vector lacks the listed macros on side.
macros is sorted alphabetically. Non-blocking.
IndirectCallUndefinedOnTarget
A first-party m:f/a referenced as arguments to a mocking or
rpc form (a meck expectation, rpc:call, erpc:call, or a CT
broker rpc helper) is neither exported nor defined by the target
tree’s module. Non-blocking: a meck expectation can install a
function the module never had, so absence proves drift, not
failure.
ExportedTypeUndefinedOnTarget
A touched .erl file adds an -export_type([t/a]) entry naming
a type neither the target version of the same module declares
nor the patch adds. An erlc error, unlike MissingType, which
is dialyzer-level; non-blocking regardless, being a target-tree
finding rather than a pin verdict. Withheld when the target file
is unreadable or declares a parse_transform, or when the added
list names a macro.
BehaviourCallbackUnknownOnPin
A touched implementer of a family-declared dependency behaviour
(FamilyDefaults.dep_behaviours) exports a callback the pinned
behaviour does not declare. The callback compiles but is never
invoked at this pin. Non-blocking: the operator judges whether
the backport still does anything useful without it.
BehaviourCallbackMissingOnPin
An added implementer of a family-declared dependency behaviour lacks a callback the pinned behaviour requires. Blocking: the missing callback crashes the first time the behaviour invokes it.
OptionKeyUnknownOnPin
An added line uses a map key that a family-declared option type
(FamilyDefaults.option_types) gained after the pinned version.
Non-blocking: an unrecognized key is typically ignored by the
older dependency rather than rejected.
SuiteNotRegisteredForCt
The patch adds a test suite to an app whose Makefile dispatches
suites by explicit registration (FamilyDefaults.suite_registration)
without registering it there. Non-blocking: the suite still
compiles, it just never runs under CI.
SchemaFeatureUnsupportedOnPin
An introduced cuttlefish schema mapping uses an attribute the pinned cuttlefish version does not support. Blocking: the corpus evidence for this shape is a boot failure.
SchemaKeyReaderMissing
An introduced cuttlefish schema mapping targets an application environment key that nothing in the target tree’s owning apps reads. Non-blocking: the token search is deliberately crude, so the operator reviews before trusting a positive.
Fields
schema_path: RelativePathsearched_apps: Vec<ApplicationName>absent_apps: Vec<ApplicationName>Apps the key names that do not exist on the target tree at all: a stronger form of the same finding.
Implementations§
Source§impl Reason
impl Reason
Sourcepub fn apply_conflict(&self) -> Option<(&Path, ApplyConflictKind)>
pub fn apply_conflict(&self) -> Option<(&Path, ApplyConflictKind)>
The risky apply outcome and its path, or None for a clean or
non-apply reason. PreimageDrifted is excluded: a drifted preimage
applies cleanly. Wildcard-free so a future apply reason must
declare its risk here, not default silently to clean.
Sourcepub fn resolver_class(&self) -> Option<ResolverClass>
pub fn resolver_class(&self) -> Option<ResolverClass>
The class this reason flagged, for a predicted-class breakdown: the absent-symbol family only. Not the corpus break class, which is the symbol that actually broke the build (the observed outcome).
pub fn is_blocking(&self) -> bool
Sourcepub fn is_path_scoped(&self) -> bool
pub fn is_path_scoped(&self) -> bool
True for reasons that are facts about files rather than the
pin’s API surface. These are the only reasons path routing may
drop for a pin that owns none of the touched paths.
Wildcard-free on purpose, like is_blocking.