kubernetes/kops · error

Could not extract flavors: %v

Error message

Could not extract flavors: %v

What it means

This error wraps a failure from gophercloud's flavors.ExtractFlavors when decoding a Nova flavor-list pagination page into a flavorList. The HTTP list call succeeded, but the response body could not be decoded into the expected flavor schema (wrong fields, non-JSON/HTML proxy error page, schema drift). It aborts defaultInstanceType's flavor search so no default instance type can be chosen for the instance group.

Source

Thrown at upup/pkg/fi/cloudup/openstack/utils.go:69

	}
	return s[i].RAM < s[j].RAM
}

func (c *openstackCloud) DefaultInstanceType(cluster *kops.Cluster, ig *kops.InstanceGroup) (string, error) {
	return defaultInstanceType(c, cluster, ig)
}

func defaultInstanceType(c OpenstackCloud, cluster *kops.Cluster, ig *kops.InstanceGroup) (string, error) {
	flavorPage, err := flavors.ListDetail(c.ComputeClient(), flavors.ListOpts{
		MinRAM: 1024,
	}).AllPages(context.TODO())
	if err != nil {
		return "", fmt.Errorf("Could not list flavors: %v", err)
	}
	var fList flavorList
	fList, err = flavors.ExtractFlavors(flavorPage)
	if err != nil {
		return "", fmt.Errorf("Could not extract flavors: %v", err)
	}
	sort.Sort(&fList)

	var candidates flavorList
	switch {
	case ig.Spec.Role.HasControlPlane():
		// Requirements based on awsCloudImplementation.DefaultInstanceType
		for _, flavor := range fList {
			if flavor.RAM >= 4096 && flavor.VCPUs >= 1 {
				candidates = append(candidates, flavor)
			}
		}

	case ig.Spec.Role.HasNode():
		for _, flavor := range fList {
			if flavor.RAM >= 4096 && flavor.VCPUs >= 2 {
				candidates = append(candidates, flavor)
			}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Inspect the wrapped inner error (%v) to see the exact JSON decode failure and which page failed.
  2. Verify with `openstack flavor list` using the same credentials that Nova's flavor endpoint returns valid JSON.
  3. Upgrade/align the gophercloud version with the target OpenStack release to fix schema mismatches.
  4. Bypass or fix any proxy/LB in front of Nova that could return non-JSON error pages.

Example fix

// before
fList, err = flavors.ExtractFlavors(flavorPage)
if err != nil {
    return "", fmt.Errorf("Could not extract flavors: %v", err)
}
// after
fList, err = flavors.ExtractFlavors(flavorPage)
if err != nil {
    return "", fmt.Errorf("extracting flavors page: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

resp, err := novaClient.Get(flavorListURL, nil, nil)
if err != nil || !strings.Contains(resp.Header.Get("Content-Type"), "application/json") {
    return fmt.Errorf("flavor endpoint did not return JSON")
}

Type guard

func isJSONPage(page gophercloud.Page) bool {
    return page != nil && page.GetBody() != nil
}

Try / catch

fList, err = flavors.ExtractFlavors(flavorPage)
if err != nil {
    return "", fmt.Errorf("Could not extract flavors: %w", err) // inspect wrapped cause
}

Prevention

When it happens

Trigger: defaultInstanceType (called by DefaultInstanceType) invokes flavors.ExtractFlavors(flavorPage) after a successful flavors.List; ExtractFlavors returns a decode error which is wrapped here: Nova returning legacy/nonstandard flavor JSON, a proxy/LB returning an HTML error page, or gophercloud schema mismatch.

Common situations: Older or non-standard OpenStack clouds whose flavor listing deviates from gophercloud's expected schema; middleware (auth interceptors, load balancers) intercepting Nova responses; wrong compute endpoint in the service catalog returning unexpected payloads; outdated gophercloud version vs the target OpenStack release.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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