dagger/dagger · error

failed to open bundle for writing: %w

Error message

failed to open bundle for writing: %w

What it means

After preparing the bundle (snapshot or parent dir), Install opens the bundle file with O_CREATE|O_APPEND|O_WRONLY to append the new CA certificates. This error wraps a failure of that OpenFile call, meaning the installer could not get a writable handle to the CA bundle.

Source

Thrown at engine/engineutil/cacerts/distros.go:450

				return fmt.Errorf("failed to set mtime of bundle during install: %w", err)
			}
			return nil
		})
	} else {
		d.createdBundleParentDir, err = d.ctrFS.MkdirAll(filepath.Dir(d.bundlePath), 0755)
		if err != nil {
			return fmt.Errorf("failed to create bundle parent dir: %w", err)
		}
		if d.createdBundleParentDir != "" {
			cleanups.append(func() error {
				return d.ctrFS.RemoveAll(d.createdBundleParentDir)
			})
		}
	}

	f, err := d.ctrFS.OpenFile(d.bundlePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		return fmt.Errorf("failed to open bundle for writing: %w", err)
	}
	defer f.Close()
	for installCert := range d.installedCerts {
		// skip installing certs that are already in the bundle
		if _, exists := d.existingBundledCerts[installCert]; exists {
			delete(d.installedCerts, installCert)
			continue
		}
		if _, err := f.WriteString(installCert + "\n\n"); err != nil {
			return err
		}
		// cleanup handled above with origBundleContents
	}
	d.updatedBundleMtime, err = d.ctrFS.MtimeOf(d.bundlePath)
	if err != nil {
		return fmt.Errorf("failed to get mtime of updated bundle: %w", err)
	}
	return nil

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Check the wrapped os error (EISDIR, EACCES, EROFS) and fix the path/permissions it indicates.
  2. Ensure the container runs with write permission on the bundle path and its parent directory.
  3. Verify nothing replaced the bundle with a directory or read-only file between preparation and open.
  4. Remount the target filesystem writable if it is mounted read-only.

Example fix

// before: container user 'nobody' cannot open /etc/ssl/certs/ca-certificates.crt for append
// after: run the container as root
// docker run --user root ... or add write capability to the custom-CA directory
Defensive patterns

Strategy: validation

Validate before calling

fi, err := os.Stat(bundlePath)
if err == nil && fi.IsDir() {
    return fmt.Errorf("%s is a directory, not a file", bundlePath)
}
if err := unix.Access(filepath.Dir(bundlePath), unix.W_OK); err != nil {
    return fmt.Errorf("no write access to %s: %w", filepath.Dir(bundlePath), err)
}

Try / catch

if err := installer.Install(ctx); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) {
        switch {
        case errors.Is(pe.Err, syscall.EACCES):
            return fmt.Errorf("run as root or fix permissions on %s", pe.Path)
        case errors.Is(pe.Err, syscall.EROFS):
            return fmt.Errorf("remount %s writable", pe.Path)
        }
    }
    return err
}

Prevention

When it happens

Trigger: ctrFS.OpenFile(d.bundlePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) fails: bundle path is a directory, parent dir is read-only or unwritable, permission denied on an existing bundle file, or the path was replaced by something non-openable after preparation.

Common situations: Non-root container without write access to /etc/ssl/certs; a bind-mount or symlink made the bundle path point at a directory; read-only root filesystem.

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 dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/5a54fd31eaf2dbee. Report an issue: GitHub.