juicedata/juicefs · error

write message: %s

Error message

write message: %s

What it means

JuiceFS clone works by writing a serialized Clone control message to the control file (.control) exposed by the FUSE mount at the SRC mount point. If the write to that control pipe fails, the command reports "write message: %s" with the underlying error — typically a broken pipe, ENOSPC/EDQUOT, or I/O error on the mount.

Source

Thrown at cmd/clone.go:145

	contentSize := 8 + 8 + 8 + 1 + uint32(len(dstName)) + 2 + 1 + 1 // +1 for threads
	wb := utils.NewBuffer(uint32(headerSize) + contentSize)
	wb.Put32(meta.Clone)
	wb.Put32(contentSize)
	wb.Put64(srcIno)
	wb.Put64(srcParentIno)
	wb.Put64(dstParentIno)
	wb.Put8(uint8(len(dstName)))
	wb.Put([]byte(dstName))
	wb.Put16(uint16(umask))
	wb.Put8(cmode)
	wb.Put8(uint8(threads))
	f, err := openController(srcMp)
	if err != nil {
		return err
	}
	defer f.Close()
	if _, err = f.Write(wb.Bytes()); err != nil {
		return fmt.Errorf("write message: %s", err)
	}

	progress := utils.NewProgress(false)
	defer progress.Done()
	bar := progress.AddCountBar("Cloning entries", 0)
	if _, errno := readProgress(f, func(count uint64, total uint64) {
		bar.SetTotal(int64(total))
		bar.SetCurrent(int64(count))
	}); errno != 0 {
		return fmt.Errorf("clone failed: %v", errno)
	}
	return nil
}

func findMountpoint(fpath string) (string, error) {
	for p := fpath; p != "/"; p = filepath.Dir(p) {
		inode, err := utils.GetFileInode(p)
		if err != nil {

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Check the mount is alive: `juicefs status META-URL` and `ls /mnt/jfs/.control`; if dead, remount with `juicefs mount`
  2. Inspect kernel logs (`dmesg | grep -i fuse`) for a FUSE abort and remount after fixing the cause
  3. Retry the clone once the mount is healthy — the operation is not partially applied if the message never reached the daemon
  4. Avoid autofs idle unmounts during long operations (raise the autofs timeout)

Example fix

# before (mount crashed)
juicefs clone /mnt/jfs/a /mnt/jfs/b  # write message: broken pipe
// after
juicefs mount redis://127.0.0.1:6379/1 /mnt/jfs
juicefs clone /mnt/jfs/a /mnt/jfs/b
Defensive patterns

Strategy: retry

Validate before calling

if _, err := os.Stat(filepath.Join(mountpoint, ".control")); err != nil {
    return fmt.Errorf("mount at %s is not serving control file: %w", mountpoint, err)
}

Try / catch

err := runClone(src, dst)
if err != nil && (strings.Contains(err.Error(), "broken pipe") || strings.Contains(err.Error(), "transport endpoint")) {
    remount(mountpoint)
    err = runClone(src, dst)
}

Prevention

When it happens

Trigger: Running `juicefs clone` when the FUSE mount has just unmounted or crashed (broken pipe / transport endpoint not connected); the control file write fails due to disk/memory pressure; the mount process was killed between openController and the Write.

Common situations: Mount daemon restarted or crashed mid-command; volume unmounted by autofs idle timeout; FUSE connection aborted (dmesg shows fuse issues); running clone against a mount whose daemon was OOM-killed.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/dd17c65e9a08973f. Report an issue: GitHub.