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
- Upgrade scaleway-sdk-go (and kOps) so scw knows the new zone/region
- Check the metadata service output: curl http://169.254.42.42/conf?format=json and inspect location.zone_id for anomalies
- 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
- Keep scaleway-sdk-go and kOps current so newly launched zones are recognized
- Sanity-check metadata location.zone_id before provisioning in a new region
- Test new Scaleway regions in a non-production cluster first
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
- error Clusters cannot span multiple regions (found zone %q,
- invalid GCE Zone: %v
- converting zone %s to region: %w
- failed to load AWS config: %w
- failed to get local-ipv4 address from ec2 metadata: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/9ed500455285df4f.
Report an issue: GitHub.