fix(glyco): name the missing GraphCheck precondition instead of throwing NullReference - #2699
Merged
trishorts merged 1 commit intoAug 4, 2026
Conversation
…erence LocalizeOGlycan ends by reading the graph terminal node, which is only populated when the peptide candidate-site motifs can accommodate every modification in the box. GlycoSearchEngine guarantees that by screening with GraphCheck first, so a search never hits this and behaviour is unchanged. Driving the graph directly without that precondition -- from a test, or from new calling code -- leaves the node null and produces a bare NullReferenceException on an array index, naming nothing. LocalizationGraph is otherwise standalone, and its own unit tests build graphs by hand, so this is a reasonable thing to do and likely to recur. Read the node once and throw MetaMorpheusException naming the box size, the candidate-site count and the precondition. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xa43sN3mQ96uLmpSNcWj9h
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2699 +/- ##
=======================================
Coverage 93.28% 93.29%
=======================================
Files 214 214
Lines 21760 21804 +44
Branches 4073 4080 +7
=======================================
+ Hits 20298 20341 +43
Misses 910 910
- Partials 552 553 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
RayMSMS
approved these changes
Aug 4, 2026
Alexander-Sol
approved these changes
Aug 4, 2026
pcruzparri
approved these changes
Aug 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
LocalizationGraph.LocalizeOGlycanfinishes by reading the graph's terminal node:https://github.com/smith-chem-wisc/MetaMorpheus/blob/3b9f634ec/MetaMorpheus/EngineLayer/GlycoSearch/LocalizationGraph.cs#L140
That node is only populated when the peptide's candidate-site motifs can actually accommodate every modification in the box.
GlycoSearchEngineguarantees it by screening withGraphCheckbefore building the graph, so in a search this is always safe and this PR changes nothing.It is not safe when the graph is driven directly. A peptide offering one candidate site against a two-glycan box leaves the terminal node null, and the symptom is a bare
NullReferenceExceptionpointing at an array index — nothing that names the missing precondition:I hit this writing a harness that builds localization graphs outside the engine, and it cost real time to trace back to the unstated
GraphCheckrequirement.LocalizationGraphis otherwise pleasantly standalone — its unit tests already construct graphs by hand — so directly-driven use is a reasonable thing to do and likely to recur.The change
Read the terminal node once, and if it is null throw
MetaMorpheusExceptionnaming the box size, the candidate-site count, and the precondition:Twelve lines including the comment, all after the scoring work. No behavioural change on any input that reaches this line today.
MetaMorpheusExceptionis the repo's fault type here rather than anArgumentExceptionbecause it is whatEngineCrashedalready reports on for engine-layer faults.Test
OGlycoTest_LocalizeOGlycan_TooFewSitesForBox_ThrowsDescriptive— one candidate site against a two-glycan box, assertingMetaMorpheusExceptionand that the message namesGraphCheck. Fails withNullReferenceExceptionbefore this change.Verification
Against
masterat3b9f634ec,--filter "FullyQualifiedName~Glyco":masterSame five failures, which are pre-existing on
masterand unrelated — they are the shared-state ordering bug fixed by #2698.Alternative considered
Returning a zero
TotalScoreinstead of throwing. Rejected: an unreachable terminal node means the caller asked for something structurally impossible, and silently scoring it zero would let a mis-specified graph flow into results looking merely unconvincing rather than invalid.🤖 Generated with Claude Code
https://claude.ai/code/session_01Xa43sN3mQ96uLmpSNcWj9h