fix(TM59): guard TM59CorridorExtendedResult against empty / index-less operativeTemperatures#9
Merged
michaldengusiak merged 1 commit intoMay 25, 2026
Conversation
…operativeTemperatures `MaxExceedableHours` and `GetHoursNumberExceeding28` both consume the `OperativeTemperatures` IndexedDoubles via `GetMaxIndex().Value` / `GetMinIndex().Value`. When the underlying collection is empty (or sparse enough that no max/min index can be derived) those `.Value` accesses on a null `Nullable<int>` throw `InvalidOperationException`, which surfaces during overheating analysis whenever a corridor result row comes back with no operative-temperature samples. Add defensive guards mirroring the existing `operativeTemperatures == null` early-return: * `operativeTemperatures.Count <= 0` → return 0 * `GetMaxIndex()` or `GetMinIndex()` is null → return 0 `MaxExceedableHours` now uses the locals from the pattern match directly (`int count = maxIndex - minIndex + 1;`) instead of re-calling the API, which also drops two redundant getter invocations on the hot path. `GetHoursNumberExceeding28` matches the same guard shape for consistency even though the body itself only iterates and doesn't dereference the indices — keeps the two methods aligned and prevents a future edit from introducing a regression. No behavioural change for callers passing well-formed results; previously crashing inputs now return 0 (matching the existing -1/null-return convention for "no useful answer" in this class). Companion to SAM_Tas PR #10 (Stage 2 perf pass) — surfaced while running the same overheating workflow used to QA that branch. The two PRs are independent code-wise but intended to ship in the same QA round. Local Framework MSBuild Release on SAM.Analytical: 0 errors. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ZiolkowskiJakub
approved these changes
May 25, 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.
Summary
Defensive guards in
TM59CorridorExtendedResultso empty operative-temperature result rows don't crash overheating analysis.MaxExceedableHoursandGetHoursNumberExceeding28both callOperativeTemperatures.GetMaxIndex().Value/GetMinIndex().Value. When the underlyingIndexedDoublesis empty (or sparse enough that no max/min index exists) those.Valueaccesses on a nullNullable<int>throwInvalidOperationException. Surfaced while running the overheating workflow used to QA the SAM_Tas Stage 2 perf branch.Adds two guards mirroring the existing
operativeTemperatures == nullearly-return:Count <= 0→ return0GetMaxIndex()/GetMinIndex()is null → return0MaxExceedableHoursnow uses the locals from the pattern-match (int count = maxIndex - minIndex + 1;) instead of re-calling the API — drops two redundant interop getter calls on the hot path.GetHoursNumberExceeding28mirrors the same guard shape for consistency even though the body itself only iterates — keeps the two methods aligned so a future edit doesn't reintroduce the bug.Behaviour
OperativeTemperatures == null-1-1(unchanged)OperativeTemperaturesInvalidOperationException0InvalidOperationException00matches the existing convention in this class for "no useful answer" cases.Companion to SAM_Tas PR
This PR is intended to ship in the same QA round as SAM-BIM/SAM_Tas#10 (Stage 2 perf pass). They are independent code-wise — the SAM_Tas PR doesn't touch TM59 — but this guard fix was surfaced during overheating-workflow QA on that branch.
Per the CI dep-clone convention (workspace-wide changes: push SAM PR first so downstream CIs find the matching
sow/**head ref), this PR opens first.Branch base:
sow/2026-Q2.Test plan
Criterion1(GetHoursNumberExceeding28() < MaxExceedableHours) —0 < 0isfalse, so empty inputs no longer cause Criterion1 to misreport via the exception path.Generated by Claude Code