kubernetes/kops · error

unable to determine region from zone %s

Error message

unable to determine region from zone %s

What it means

VerifyToken derives the Scaleway region from the zone reported by the instance metadata service. scw.ParseZone succeeds, but zone.Region() fails because the parsed zone string does not encode a known region (a Scaleway zone is <region><digit>, e.g. fr-par-1). kOps cannot scope the subsequent IPAM ListIPs call to a region, so it aborts token verification.

Source

Thrown at upup/pkg/fi/cloudup/scaleway/verifier.go:78

func (v scalewayVerifier) VerifyToken(ctx context.Context, rawRequest *http.Request, token string, body []byte) (*bootstrap.VerifyResult, error) {
	if !strings.HasPrefix(token, scalewaymetadata.ScalewayAuthenticationTokenPrefix) {
		return nil, bootstrap.ErrNotThisVerifier
	}
	serverID := strings.TrimPrefix(token, scalewaymetadata.ScalewayAuthenticationTokenPrefix)

	metadataAPI := instance.NewMetadataAPI()
	metadata, err := metadataAPI.GetMetadata()
	if err != nil {
		return nil, fmt.Errorf("failed to retrieve server metadata: %w", err)
	}
	zone, err := scw.ParseZone(metadata.Location.ZoneID)
	if err != nil {
		return nil, fmt.Errorf("unable to parse Scaleway zone %q: %w", metadata.Location.ZoneID, err)
	}
	region, err := zone.Region()
	if err != nil {
		return nil, fmt.Errorf("unable to determine region from zone %s", zone)
	}

	profile, err := scalewaymetadata.CreateValidScalewayProfile()
	if err != nil {
		return nil, err
	}
	scwClient, err := scw.NewClient(
		scw.WithProfile(profile),
		scw.WithUserAgent(KopsUserAgentPrefix+kopsv.Version),
	)
	if err != nil {
		return nil, fmt.Errorf("creating client for Scaleway Verifier: %w", err)
	}

	serverResponse, err := instance.NewAPI(scwClient).GetServer(&instance.GetServerRequest{
		ServerID: serverID,
		Zone:     zone,
	}, scw.WithContext(ctx))

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Upgrade scaleway-sdk-go (and kOps) so scw knows the new zone/region
  2. Check the metadata service output: curl http://169.254.42.42/conf?format=json and inspect location.zone_id for anomalies
  3. As a last resort, patch/derive the region manually with strings.TrimRight on digits before calling zone.Region()

Example fix

// before
region, err := zone.Region()
if err != nil {
	return nil, fmt.Errorf("unable to determine region from zone %s", zone)
}
// after
region, err := zone.Region()
if err != nil {
	return nil, fmt.Errorf("unable to determine region from zone %s: %w", zone, err)
}
Defensive patterns

Strategy: validation

Validate before calling

zoneID := metadata.Location.ZoneID
z, err := scw.ParseZone(zoneID)
if err != nil { return err }
if _, err := z.Region(); err != nil {
	return fmt.Errorf("zone %q has no known region; upgrade scaleway-sdk-go", zoneID)
}

Type guard

func zoneHasRegion(zoneID string) bool {
	z, err := scw.ParseZone(zoneID)
	return err == nil && z.Region() == nil
}

Try / catch

if err != nil {
	if _, ok := err.(*scw.ResponseError); ok {
		log.Printf("scaleway API error during region lookup: %v", err)
	}
	return fmt.Errorf("unable to determine region from zone %s: %w", zone, err)
}

Prevention

When it happens

Trigger: The instance metadata service returns a Location.ZoneID that parses as a scw.Zone but has no extractable region — e.g. a zone string like 'par1' or an unexpected/custom zone identifier that is not of the <region>-<index> form known to the SDK.

Common situations: Running a node on a Scaleway zone the installed scaleway-sdk-go version does not know (new region launched before SDK upgrade), or a mock/custom metadata endpoint returning a non-canonical zone id during testing.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/9ed500455285df4f. Report an issue: GitHub.