dagger/dagger · error
failed to lstat %s: %w
Error message
failed to lstat %s: %w
What it means
nixosLike.Install calls ctrFS.Lstat on the CA bundle path to determine whether it's a symlink, a missing file, or something else. ErrNotExist means the bundle doesn't exist yet (commonInstaller will create it) and a symlink triggers the swap logic; any other Lstat error aborts installation with this wrapped error.
Source
Thrown at engine/engineutil/cacerts/distros.go:261
targetPath := target
if !filepath.IsAbs(targetPath) {
targetPath = filepath.Join(filepath.Dir(d.bundlePath), targetPath)
}
content, err := d.ctrFS.ReadFile(targetPath)
if err != nil {
return fmt.Errorf("failed to read symlink target %s for %s: %w", targetPath, d.bundlePath, err)
}
if err := d.ctrFS.Remove(d.bundlePath); err != nil {
return fmt.Errorf("failed to remove symlink %s: %w", d.bundlePath, err)
}
if err := d.ctrFS.WriteFile(d.bundlePath, content, 0o644); err != nil {
return fmt.Errorf("failed to materialize %s: %w", d.bundlePath, err)
}
d.origSymlinkTarget = target
case errors.Is(err, os.ErrNotExist):
// No bundle yet — commonInstaller will create one.
case err != nil:
return fmt.Errorf("failed to lstat %s: %w", d.bundlePath, err)
}
return d.commonInstaller.Install(ctx)
}
func (d *nixosLike) Uninstall(ctx context.Context) error {
// Run commonInstaller's uninstall regardless of whether we swapped the
// symlink. Capture its error and keep going — the symlink restore below
// is the only thing that frees up the materialized bundle (which may still
// contain the cert if commonInstaller.Uninstall failed).
rerr := d.commonInstaller.Uninstall(ctx)
if d.origSymlinkTarget == "" {
return rerr
}
target := d.origSymlinkTarget
d.origSymlinkTarget = ""
if err := d.ctrFS.Remove(d.bundlePath); err != nil && !errors.Is(err, os.ErrNotExist) {
rerr = errors.Join(rerr, fmt.Errorf("failed to remove materialized bundle %s: %w", d.bundlePath, err))
}View on GitHub (pinned to 82ba2681db)
Solutions
- Check the wrapped cause: if ENOTDIR/ENOENT on the parent, create the directory or fix SSL_CERT_FILE to a valid absolute path
- Ensure /etc/ssl/certs exists and is traversable in the image
- Fix permissions so the engine process can stat the path
- If SSL_CERT_FILE points somewhere invalid, unset it so the default bundle path is used
Defensive patterns
Strategy: validation
Validate before calling
if fi, err := os.Stat("/etc/ssl/certs"); err != nil || !fi.IsDir() {
return fmt.Errorf("/etc/ssl/certs must be a traversable directory in the image")
}
if v, ok := os.LookupEnv("SSL_CERT_FILE"); ok && !filepath.IsAbs(v) {
return fmt.Errorf("SSL_CERT_FILE must be an absolute path, got %q", v)
} Prevention
- Ensure /etc/ssl/certs exists as a directory in Nix/distroless images
- Only set SSL_CERT_FILE to valid absolute paths
- Check snapshot health if EIO errors appear
- Verify permissions allow stat on the bundle path for rootless runs
When it happens
Trigger: ctrFS.Lstat(d.bundlePath) returns an unexpected error (EACCES, EIO, ENOTDIR, etc.) during nixosLike.Install — e.g. /etc/ssl/certs doesn't exist as a directory or is unreadable.
Common situations: Minimal Nix/distroless images missing /etc/ssl/certs as a traversable directory; permission-restricted rootless containers; I/O errors on damaged snapshots.
Related errors
- failed to remove materialized bundle: %w
- failed to evaluate symlinks for %s: %w
- failed to restore symlink %s -> %s: %w
- failed to readlink %s: %w
- failed to read symlink target %s for %s: %w
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/d914fdae71ca6034.
Report an issue: GitHub.