Skip to content

fix(aws): GetCapacityBlockOfferings/Reservations/Blocks drop per-region errors - #152

Merged
scttfrdmn merged 1 commit into
mainfrom
fix/110-capacity-blocks-region-errors
Aug 19, 2026
Merged

scttfrdmn merged 1 commit into
mainfrom
fix/110-capacity-blocks-region-errors

Conversation

@scttfrdmn

Copy link
Copy Markdown
Contributor

Summary

Verification against live AWS

Account 942542972736, us-west-2:

  • c7i.4xlarge, m5.large, g7e.4xlarge, trn2.48xlarge → all return the exact InvalidParameterValue: ... is not supported for Capacity Blocks ... message the classifier matches.
  • p5.48xlarge → hits a genuine CapacityBlockDescribeLimitExceeded service-limit error, correctly not classified as ineligible (verified isCapacityBlockIneligible returns false and the CLI surfaces the real AWS message unchanged).

Test plan

  • TestGetCapacityReservations_Empty/_MultiRegion and TestGetCapacityBlocks_Empty asserted the bug — they only passed because Substrate doesn't implement DescribeCapacityReservations (answers InvalidAction) and the old code discarded that error. Replaced with _AllRegionsFailed/_MultiRegionAllFailed variants asserting the [HIGH] SearchInstanceTypes/GetSpotPricing return success even when every region query fails #63 contract, matching the precedent in TestGetCapacityBlockOfferings_AllRegionsFailed (Capacity Blocks for ML: instance-count gating, CB-only types, eligibility allowlist, 24h floor, utilization break-even #109).
  • New pkg/aws/client_ineligible_test.go: classifier unit tests (ineligible vs. service-limit vs. access-denied vs. throttled vs. non-API error), allIneligible aggregation, and newUnreachableClient-backed all-regions-fail tests for GetCapacityReservations/GetCapacityBlocks.
  • Confirmed regression: reverting just GetCapacityReservations/GetCapacityBlocks to the pre-fix implementation makes the new _AllRegionsFail tests fail with "expected an error ... got nil" — verified explicitly before restoring the fix.
  • go build ./..., go vet ./..., go test ./... all green
  • golangci-lint run ./pkg/aws/... — 0 issues
  • make check-docs clean
  • CHANGELOG.md updated under ## [Unreleased]

Fixes #110

@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.18182% with 14 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/aws/client.go 68.18% 12 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

…on errors

GetCapacityBlockOfferings buffered per-region errors, printed them only
under --verbose, and always returned (results, nil) — the exact pattern
already fixed in #63/#109 for other discovery paths, but this function
was added afterward (#67) and reintroduced it. GetCapacityReservations
and GetCapacityBlocks had the identical shape and were never fixed at
all. Since "no capacity" is a common, legitimate answer for all three
calls, a total failure (expired credentials, an SCP denial, throttling)
was indistinguishable from genuinely empty inventory.

All three now apply the same #63 contract as SearchInstanceTypes: an
error when every queried region fails, an unconditional stderr warning
for a partial failure so a degraded result stays visible.

Also adds aws.ErrCapacityBlockIneligible: DescribeCapacityBlockOfferings
returns InvalidParameterValue with a distinct, stable message
("... is not supported for Capacity Blocks ...") when an instance type
simply isn't a Capacity Block type at all — a different, permanent
answer from a transient query failure, and previously indistinguishable
from one. Callers can check for it via errors.Is; when every queried
region reports ineligibility (not a mix of ineligibility and real
failures), the aggregate error names that specifically rather than the
generic "all N region queries failed".

Verified live against account 942542972736: c7i.4xlarge, m5.large,
g7e.4xlarge, and trn2.48xlarge all return the exact ineligibility
message classified here; p5.48xlarge hits a genuine service-limit error
instead, which is correctly NOT classified as ineligible.

TestGetCapacityReservations_Empty/_MultiRegion and
TestGetCapacityBlocks_Empty asserted the bug: they only passed because
Substrate doesn't implement DescribeCapacityReservations (answers
InvalidAction) and the old code discarded that error. Replaced with
_AllRegionsFailed/_MultiRegionAllFailed variants asserting the #63
contract instead, matching TestGetCapacityBlockOfferings_AllRegionsFailed
from #109's fix.

Fixes #110
@scttfrdmn
scttfrdmn force-pushed the fix/110-capacity-blocks-region-errors branch from a1df5e3 to a40cab6 Compare August 19, 2026 04:54
@scttfrdmn
scttfrdmn merged commit 7470de5 into main Aug 19, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GetCapacityBlockOfferings drops per-region errors (regression of #63) — 'no capacity' is indistinguishable from AccessDenied or ineligible

1 participant