containerd/containerd · error

failed to truncate file %q: %w

Error message

failed to truncate file %q: %w

What it means

Thrown by mount manager's mkfs-based Transform when os.File.Truncate fails while sizing a new sparse/backing file for a writable block image (e.g. ext4 formatted loopback device). The wrapped error is the underlying ftruncate(2)/syscall failure; the mount is not created. It indicates the backing file could not be resized to the requested size before formatting.

Source

Thrown at core/mount/manager/mkfs.go:129

			binary = "mkfs.xfs"
			if id != "" {
				createArgs = append(createArgs, []string{"-m", fmt.Sprintf("uuid=%s", id)}...)
			}
		default:
			return mount.Mount{}, fmt.Errorf("unsupported filesystem %q: %w", fs, errdefs.ErrInvalidArgument)
		}

		f, err := r.OpenFile(subpath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0640)
		if err != nil {
			return mount.Mount{}, fmt.Errorf("failed to create file %q: %w", m.Source, err)
		}

		createArgs = append(createArgs, f.Name())

		err = f.Truncate(size)
		f.Close()
		if err != nil {
			return mount.Mount{}, fmt.Errorf("failed to truncate file %q: %w", m.Source, err)
		}

		if err := createWritableImage(ctx, binary, createArgs...); err != nil {
			return mount.Mount{}, fmt.Errorf("failed format %q: %w", m.Source, err)
		}
	} else {
		return mount.Mount{}, fmt.Errorf("failed to stat %q: %w", m.Source, err)
	}

	return m, nil
}

func createWritableImage(ctx context.Context, binary string, args ...string) error {
	cmd := exec.CommandContext(ctx, binary, args...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%s failed: %s: %w", filepath.Base(binary), out, err)
	}

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Check free space on the filesystem holding the Source file (df -h) and free space or reduce the requested size.
  2. Verify the process user has write permission on the Source path's directory.
  3. Ensure the requested size is a valid positive value within fs limits (check the size field passed to Transform).
  4. If on a read-only rootfs, move the image path to a writable volume.

Example fix

// before
createArgs = append(createArgs, f.Name())
err = f.Truncate(size) // fails with ENOSPC
// after
if err := checkFreeSpace(filepath.Dir(m.Source), size); err != nil {
    return mount.Mount{}, fmt.Errorf("insufficient space for %q: %w", m.Source, err)
}
err = f.Truncate(size)
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(filepath.Dir(m.Source))
if err != nil { return fmt.Errorf("image dir unavailable: %w", err) }
if size <= 0 { return errors.New("image size must be positive") }
if st, err := statfs(filepath.Dir(m.Source)); err == nil && uint64(size) > st.Avail { return errors.New("insufficient disk space") }

Type guard

func validImageTarget(path string, size int64) bool {
    st, err := os.Stat(filepath.Dir(path))
    return err == nil && st.IsDir() && size > 0
}

Try / catch

var merr *mountError
if err := mgr.Transform(ctx, mnt); err != nil {
    if strings.Contains(err.Error(), "failed to truncate") {
        // inspect wrapped syscall error: ENOSPC -> free space; EACCES -> permissions
        var pe *os.PathError
        if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) { freeSpaceAndRetry() }
    }
}

Prevention

When it happens

Trigger: Calling the manager Transform (New/Create mount flow) for a mount whose Source is a file that must be created and truncated to `size`; f.Truncate(size) returns a non-nil error (permission denied, ENOSPC, size negative or exceeding filesystem limits, file on read-only fs).

Common situations: Creating a loopback-backed writable snapshot on a full disk (ENOSPC); target directory not writable by the daemon user; requesting a size larger than the backing filesystem allows; Source path pointing at a read-only bind location.

Related errors


AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02). Data as JSON: /api/errors/90889e2e5edfccb3. Report an issue: GitHub.