kubernetes/kops · error

error opening

Error message

error opening %q: %w

What it means

newWriter opens (creating or truncating) the trace output file at cfg.path with os.OpenFile(O_RDWR|O_CREATE|O_TRUNC, 0600). Any OS-level failure opening that file is wrapped as "error opening %q: %w" and propagated to Start.

Solutions

  1. Create the parent directory of cfg.path before starting the exporter (os.MkdirAll).
  2. Ensure the process user has write permission (mode 0600 is applied; directory needs write+execute).
  3. Point cfg.path at a mounted, writable volume; check it is not a directory.
  4. Check filesystem is writable (not read-only, not full).

Example fix

// before
cfg := Config{Path: "/var/log/traces.bin"} // dir may not exist
// after
os.MkdirAll("/var/log", 0755)
cfg := Config{Path: "/var/log/traces.bin"}
Defensive patterns

Strategy: validation

Validate before calling

if dir := filepath.Dir(cfg.Path); dir != "" {
    if err := os.MkdirAll(dir, 0755); err != nil { return err }
}
if fi, err := os.Stat(cfg.Path); err == nil && fi.IsDir() {
    return fmt.Errorf("%s is a directory", cfg.Path)
}

Try / catch

if err := client.Start(ctx); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) { /* fix path/permissions before retry */ }
    return err
}

Prevention

When it happens

Trigger: cfg.path points to a non-existent directory; the path exists but is a directory; missing write permission; read-only filesystem or full disk causing unexpected open failure.

Common situations: Misconfigured OTEL file exporter path in a container (path not mounted/volume not writable); running nodeup/exporter as a non-root user writing to a root-only directory; SELinux/AppArmor blocking the path.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at pkg/otel/otlptracefile/writer.go:46

	"google.golang.org/protobuf/proto"
	"k8s.io/kops/pkg/otel/otlptracefile/pb"
)

type writer struct {
	fileMutex sync.Mutex
	f         *os.File

	typeCodesMutex sync.Mutex
	nextTypeCode   TypeCode
	typeCodes      map[string]TypeCode
}

type TypeCode uint32

func newWriter(cfg Config) (*writer, error) {
	f, err := os.OpenFile(cfg.path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return nil, fmt.Errorf("error opening %q: %w", cfg.path, err)
	}
	w := &writer{
		f: f,
	}
	w.nextTypeCode = 32
	w.typeCodes = make(map[string]TypeCode)
	w.recordWellKnownType(pb.WellKnownTypeCode_WellKnownTypeCode_ObjectType, &pb.ObjectType{})

	return w, nil
}

// writeTraces is called by the otel libraries to write a set of trace records.
func (w *writer) writeTraces(ctx context.Context, req *coltracepb.ExportTraceServiceRequest) error {
	return w.writeObject(ctx, req)
}

// codeForType returns the integer code value for objects of obj.
// If this is the first time we've seen the type, this method will assign a code value, write it to the file and return it.

View on GitHub (pinned to 4c8573c808)