kubernetes/kops · error

listing resources for %v: %w

Error message

listing resources for %v: %w

What it means

The worker dumpGVRNamespaces lists objects for each (GVR, namespace) job via the dynamic client. Client-side HTTP errors with status 4xx (e.g. 403 forbidden, 404 gone) are silently skipped; anything else — 5xx server errors, 429 throttling outside client rate limiting, timeouts, connection resets — is sent to the results channel wrapped as "listing resources for %v: %w". These are collected and joined by DumpResources, so one failing resource does not abort the whole dump.

Source

Thrown at pkg/dump/resourcedumper.go:201

	return gvrNamespaces, nil
}

func (d *resourceDumper) dumpGVRNamespaces(ctx context.Context, jobs chan gvrNamespace, results chan resourceDumpResult) {
	for job := range jobs {
		var lister dynamic.ResourceInterface
		if job.namespace != "" {
			lister = d.dynamicClient.Resource(job.gvr).Namespace(job.namespace)
		} else {
			lister = d.dynamicClient.Resource(job.gvr)
		}
		resourceList, err := lister.List(ctx, metav1.ListOptions{})
		if err != nil {
			var statusErr *k8sErrors.StatusError
			if errors.As(err, &statusErr) && statusErr.ErrStatus.Code >= 400 && statusErr.ErrStatus.Code < 500 {
				continue
			}
			results <- resourceDumpResult{
				err: fmt.Errorf("listing resources for %v: %w", job, err),
			}
			continue
		}
		resPath := path.Join(d.artifactsDir, "cluster-info", fmt.Sprintf("%v.%v", job.String(), d.output))
		err = os.MkdirAll(path.Dir(resPath), 0755)
		if err != nil {
			results <- resourceDumpResult{
				err: fmt.Errorf("creating directory %q: %w", resPath, err),
			}
			continue
		}
		resFile, err := os.Create(resPath)
		if err != nil {
			results <- resourceDumpResult{
				err: fmt.Errorf("creating file %q: %w", resPath, err),
			}
			continue
		}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Read the wrapped cause: 5xx/timeouts usually mean server overload — retry with fewer concurrent workers or a larger context timeout.
  2. Reduce resourceDumpConcurrency or the resource set (discovery is currently listing every namespaced GVR x every namespace).
  3. Ensure the caller's context is not cancelled prematurely during the dump.
  4. If a specific GVR consistently fails, check the API server/etcd logs for that resource's storage errors and fix or exclude the CRD.
Defensive patterns

Strategy: try-catch

Validate before calling

// precondition: stable API server; e.g.
if _, err := client.Discovery().ServerVersion(); err != nil {
	return fmt.Errorf("API server unhealthy before dump: %w", err)
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
defer cancel()

Type guard

func isRetryableListError(err error) bool {
	if k8sErrors.IsServerTimeout(err) || k8sErrors.IsTooManyRequests(err) || k8sErrors.IsInternalError(err) {
		return true
	}
	var se *k8sErrors.StatusError
	if errors.As(err, &se) {
		return se.ErrStatus.Code >= 500 // 4xx list failures are skipped by the dumper anyway
	}
	return errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) == false && errors.Is(err, io.EOF)
}

Try / catch

if err := dumper.DumpResources(ctx); err != nil {
	if isRetryableListError(err) {
		// 5xx/timeouts: back off, optionally reduce concurrency, retry
	}
	if errors.Is(err, context.Canceled) {
		// caller cancelled mid-dump: expected, not a dump defect
	}
	return err
}

Prevention

When it happens

Trigger: API server returns 5xx (etcd overload, apiserver crashloop), the context is cancelled mid-list, connection drops, or the client exhausts retries. Note 4xx StatusErrors are intentionally skipped, so this only fires for non-StatusError or 5xx/non-listed-code failures.

Common situations: Large clusters timing out on list (list cost too high for etcd); API server under memory pressure returning 500; caller cancelling ctx during dump; flaky network to the control plane; resource removed between discovery and list (usually skipped as 404, not this error).

Related errors


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