rancher/rancher · error

failed to read chart: %w

Error message

failed to read chart: %w

What it means

ChartValuesWriter.processChart reads the whole chart values stream with io.ReadAll (pkg/codegen/buildconfig/chart_writer.go:41-44); nil readers are rejected earlier at line 34, so this error means the reader itself failed mid-read. This is the buildconfig codegen tool that injects build.yaml-driven values into chart/values.yaml.

Source

Thrown at pkg/codegen/buildconfig/chart_writer.go:43

		return errors.New("nil config")
	}
	if err := w.processChart(); err != nil {
		return err
	}
	return nil
}

func (w *ChartValuesWriter) processChart() error {
	if w.Chart == nil {
		return errors.New("nil chart input")
	}
	if w.Output == nil {
		return errors.New("nil output")
	}

	chartContent, err := io.ReadAll(w.Chart)
	if err != nil {
		return fmt.Errorf("failed to read chart: %w", err)
	}

	// Parse chart as YAML to get line numbers for values
	var chartRoot yaml.Node
	if err := yaml.Unmarshal(chartContent, &chartRoot); err != nil {
		return fmt.Errorf("failed to parse chart YAML: %w", err)
	}

	// Collect line-based replacements instead of modifying the AST
	replacements := make(map[int]string) // line number -> new value
	if err := w.collectReplacements(&chartRoot, replacements); err != nil {
		return fmt.Errorf("failed to collect replacements: %w", err)
	}

	// Apply replacements line-by-line to preserve all formatting
	return w.applyReplacements(chartContent, replacements)
}

View on GitHub (pinned to 932558d4e6)

Solutions

  1. Ensure the reader is open and not already consumed before calling Run()
  2. If reading from a file, open it fresh (os.Open) inside the run and check that error separately
  3. Read the wrapped I/O error — it names the failing operation (file closed, broken pipe, etc.)
  4. Buffer the input into memory first (bytes.Buffer/bytes.Reader) so I/O errors surface before processing

Example fix

// before
w := &ChartValuesWriter{Config: cfg, Chart: resp.Body /* already closed */, Output: out}
err := w.Run()

// after
content, err := io.ReadAll(resp.Body)
if err != nil { return err }
w := &ChartValuesWriter{Config: cfg, Chart: bytes.NewReader(content), Output: out}
err = w.Run()
Defensive patterns

Strategy: validation

Validate before calling

// buffer input first so I/O failures surface with context before Run()
content, readErr := io.ReadAll(chartReader)
if readErr != nil {
	return fmt.Errorf("reading chart values: %w", readErr)
}
w := &ChartValuesWriter{Config: cfg, Chart: bytes.NewReader(content), Output: out}

Try / catch

if err := w.Run(); err != nil {
	if strings.Contains(err.Error(), "failed to read chart") {
		// input stream problem: verify the file/pipe feeding w.Chart is open
	}
	return err
}

Prevention

When it happens

Trigger: w.Chart is a reader that errors during Read: a closed HTTP response body, a file closed or removed concurrently, a pipe whose writer failed, or a custom reader returning an error.

Common situations: CI codegen reading values.yaml from a substituted stream (curl pipe, process substitution) that terminates early; passing an already-closed *os.File; concurrent writers replacing the file mid-read.

Related errors


AI-assisted analysis of rancher/rancher@932558d4e6 (2026-08-16). Data as JSON: /api/errors/5d9a0a0d55d26b58. Report an issue: GitHub.