kubernetes/kops · error

reading data: %v

Error message

reading data: %v

What it means

S3Path.RenderTerraform (used by the DigitalOcean Spaces backend) first buffers the entire input with io.ReadAll. This error is returned when reading from the supplied io.Reader fails before any Terraform rendering starts — no data was consumed from the caller's reader beyond the failure point.

Source

Thrown at util/pkg/vfs/s3fs.go:705

type terraformDOFile struct {
	Bucket  string                   `json:"bucket" cty:"bucket"`
	Region  string                   `json:"region" cty:"region"`
	Key     string                   `json:"key" cty:"key"`
	Content *terraformWriter.Literal `json:"content,omitempty" cty:"content"`
}

type terraformScwFile struct {
	Bucket  string                   `json:"bucket" cty:"bucket"`
	Key     string                   `json:"key" cty:"key"`
	Content *terraformWriter.Literal `json:"content,omitempty" cty:"content"`
}

func (p *S3Path) RenderTerraform(w *terraformWriter.TerraformWriter, name string, data io.Reader, acl ACL) error {
	ctx := context.TODO()

	bytes, err := io.ReadAll(data)
	if err != nil {
		return fmt.Errorf("reading data: %v", err)
	}

	// render DO's terraform
	switch p.scheme {
	case "do":

		content, err := w.AddFileBytes("digitalocean_spaces_bucket_object", name, "content", bytes, false)
		if err != nil {
			return fmt.Errorf("error rendering DO file: %w", err)
		}

		// retrieve space region from endpoint
		endpoint := os.Getenv("S3_ENDPOINT")
		if endpoint == "" {
			return errors.New("S3 Endpoint is empty")
		}
		region := strings.Split(endpoint, ".")[0]

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Fix the underlying reader: check that the source file exists, is readable, and is opened before calling RenderTerraform.
  2. If the reader wraps a network body, read/validate it yourself first and handle errors before rendering.
  3. Read the wrapped %v cause in the message to identify whether it's a permissions, EOF, or closed-stream error.
  4. Where possible pass in-memory bytes ([]byte reader) to eliminate reader-side failure modes.

Example fix

// before
err := p.RenderTerraform(w, name, bytes.NewReader(data), acl)
// replaced failing file reader
data, err := os.ReadFile(configPath)
if err != nil { return err } // fail early with a clear error
err = p.RenderTerraform(w, name, bytes.NewReader(data), acl)
Defensive patterns

Strategy: validation

Validate before calling

// fail fast if the source reader cannot provide data
if f, ok := data.(*os.File); ok {
    if _, err := f.Stat(); err != nil || f == nil { return fmt.Errorf("unusable reader: %w", err) }
}
// or buffer it yourself first:
buf, err := io.ReadAll(data)
if err != nil { return err } // surface the reader error with your own context

Try / catch

bytes, err := io.ReadAll(data)
if err != nil { return fmt.Errorf("preflight read of terraform input: %w", err) }
err = p.RenderTerraform(w, name, bytes.NewReader(buf), acl) // in-memory readers can't fail here

Prevention

When it happens

Trigger: Calling RenderTerraform (indirectly via terraform writers that pass an io.Reader) with a reader backed by a failing source: an already-closed file, a failed HTTP body, or an OS I/O error during the read.

Common situations: Terraform output generation where a config file was truncated or unreadable on disk; passing a response body that already errored upstream; permissions issues on local cluster state files.

Related errors


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