juicedata/juicefs · error
open control file for [%d:%s]: %w
Error message
open control file for [%d:%s]: %w
What it means
doCompact sends a compact request by writing to the .control file exposed by the JuiceFS FUSE mount at the given path. openController opens .control under the mount point; if the open fails (path not on a JuiceFS mount, mount dead, permission denied), the error is wrapped as "open control file for [%d:%s]: %w" with the inode and path.
Source
Thrown at cmd/compact.go:93
continue
}
inode := meta.Ino(inodeNo)
if !inode.IsValid() {
logger.Fatalf("inode numbe %d not valid", inode)
}
if err = doCompact(inode, path, uint16(coCnt)); err != nil {
logger.Error(err)
}
}
return nil
}
func doCompact(inode meta.Ino, path string, coCnt uint16) error {
f, err := openController(path)
if err != nil {
return fmt.Errorf("open control file for [%d:%s]: %w", inode, path, err)
}
defer f.Close()
headerLen, bodyLen := uint32(8), uint32(8+2)
wb := utils.NewBuffer(headerLen + bodyLen)
wb.Put32(meta.CompactPath)
wb.Put32(bodyLen)
wb.Put64(uint64(inode))
wb.Put16(coCnt)
_, err = f.Write(wb.Bytes())
if err != nil {
logger.Fatalf("write message: %s", err)
}
progress := utils.NewProgress(false)
bar := progress.AddCountBar("Compacted chunks", 0)
_, errno := readProgress(f, func(totalChunks, currChunks uint64) {View on GitHub (pinned to c9a67b23e8)
Solutions
- Confirm the path is on a live JuiceFS mount: `ls <mountpoint>/.control` and `mount | grep juicefs`; remount if absent
- Use the mount point path (not a subpath on another filesystem) as the compact argument
- Run with sufficient privileges (root or the mounting user) to open .control
- Check mount daemon logs (`juicefs mount` log) for the reason the FUSE connection is gone, fix, and remount
Example fix
// before juicefs compact /tmp/data # open control file for [2:/tmp/data]: ... // after juicefs mount redis://127.0.0.1:6379/1 /mnt/jfs juicefs compact /mnt/jfs/data
Defensive patterns
Strategy: try-catch
Validate before calling
ctrl := filepath.Join(mountpoint, ".control")
if _, err := os.OpenFile(ctrl, os.O_WRONLY, 0); err != nil {
return fmt.Errorf("control file %s not writable: %w", ctrl, err)
} Try / catch
if err := runCompact(path); strings.Contains(err.Error(), "open control file for") {
remount(mountpoint); err = runCompact(path)
} Prevention
- Pass a path inside a live JuiceFS mount to `juicefs compact`
- Verify .control exists at the mount root before batch compaction
- Run compact as root or the user that performed the mount
- Keep the mount daemon supervised (systemd) so it does not exit mid-command
When it happens
Trigger: Running `juicefs compact <path>` where <path> is not inside a mounted JuiceFS volume, the FUSE mount has crashed/unmounted, or the user lacks permission to open .control in the mount root.
Common situations: Compact invoked with a typo'd or local-filesystem path; mount daemon exited between listing inodes and compacting; running as non-root on a mount where .control is restricted; autofs unmounted the volume before the command ran.
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
- write message: %s
- the clone DST path should be at the same mount point as the
- clone failed: %v
- %s is not inside JuiceFS
- path %s is not a mount point
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/8d2c3d09aae37ab4.
Report an issue: GitHub.