Skip to content

Unreachable enabled region fails entire multi-region query with regions = ["*"]; no way to exclude a region #2782

Description

@kaidaguerre

Summary

When a connection uses regions = ["*"] and one enabled (opted-in) region's endpoint is unreachable at the network level, every multi-region query fails — slowly. There is no config mechanism that can exclude the broken region without abandoning the wildcard, and no way to make transport-level failures non-fatal.

Observed in production with me-south-1 (Bahrain): the region is opted-in at the org level but runs no workloads, and TCP connections to ec2.me-south-1.amazonaws.com time out from the querying environment. Every query against a multi-region table then fails after several minutes:

aws_vpc_security_group.listVpcSecurityGroups: api_error="operation error EC2: DescribeSecurityGroups,
exceeded maximum number of attempts, 11, https response error StatusCode: 0, RequestID: ,
request send failed, Post \"https://ec2.me-south-1.amazonaws.com/\": dial tcp 99.82.136.87:443: i/o timeout"
...
streamRows execution has failed: calling queryCache.AbortSet (aws: exceeded allowed timeout)

Mechanics

  1. regions = ["*"] is expanded in listQueryRegionsForConnection (aws/multi_region.go) to all regions enabled for the account — including opted-in regions that are unreachable from where Steampipe runs. Patterns support * and ? only; there is no negation or exclusion.
  2. The client uses the AWS SDK standard retryer (getClientWithMaxRetries, aws/service.go) with the SDK's default HTTP client timeouts. request send failed / dial tcp ... i/o timeout is classified as a retryable connection error, so the SDK retries the full max_error_retry_attempts budget. Each attempt waits up to the default 30s dial connect timeout (DefaultDialConnectTimeout in aws-sdk-go-v2), plus exponential backoff between attempts — an unreachable region burns multiple minutes before returning anything.
  3. By then the query's context deadline has usually expired, so the whole scan aborts with exceeded allowed timeout. One dead region fails all regions.

Why no existing config option solves this

  • regions: to exclude one region you must enumerate every wanted region explicitly and keep the list current as AWS launches/opts-in regions — the wildcard's main value is lost.
  • ignore_error_codes: matches smithy.APIError codes only (shouldIgnoreErrors, aws/errors.go). A dial timeout never reaches the API layer — StatusCode 0, no error code — so it can never match.
  • ignore_error_messages: does regex-match the full error string, so it can swallow the failure — but only after the retry budget is exhausted, so the multi-minute stall remains, and broad patterns (i/o timeout) silently hide genuine failures in healthy regions too. It is also not exposed in all managed environments (e.g. Turbot Pipes connection config), while regions, max_error_retry_attempts, min_error_retry_delay, and ignore_error_codes are.
  • max_error_retry_attempts: lowering it makes the query fail faster, not succeed.

Proposals

  1. Region exclusion in config. Support negation patterns in regions (e.g. regions = ["*", "!me-south-1"]) or a new exclude_regions argument, applied after wildcard expansion in listQueryRegionsForConnection. Small, backwards-compatible, and gives wildcard users a surgical opt-out.
  2. Fail fast on transport-level errors. An endpoint that cannot be dialed is not throttling; retrying it max_error_retry_attempts times with 30s connect timeouts is wasted wall-clock. Classify request send failed connection errors as non-retryable (or cap them at 1–2 attempts) so an unreachable region surfaces its error in seconds instead of minutes.
  3. (Optional, opt-in) per-region error isolation. A flag that makes a region whose List call fails with a transport error contribute zero rows plus a warning, instead of failing the entire multi-region scan. Trade-off: silent data gaps — hence opt-in, not default.

Proposal 1 alone resolves the operational problem; proposal 2 improves failure behavior for everyone regardless.

Environment

  • steampipe-plugin-aws (current), multi-region connection with regions = ["*"]
  • Region opted-in but unused; endpoint resolves to a Global Accelerator address (99.82.x.x) that is unreachable from the querying network. Why the endpoint is unreachable is environment-specific and out of scope here — the plugin behavior (slow total failure, no exclusion mechanism) is the issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions