{"record":{"id":"8d2c3d09aae37ab4","repo":"juicedata/juicefs","slug":"open-control-file-for-d-s-w","errorCode":null,"errorMessage":"open control file for [%d:%s]: %w","messagePattern":"open control file for \\[(.+?):(.+?)\\]: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/compact.go","lineNumber":93,"sourceCode":"\t\t\tcontinue\n\t\t}\n\t\tinode := meta.Ino(inodeNo)\n\n\t\tif !inode.IsValid() {\n\t\t\tlogger.Fatalf(\"inode numbe %d not valid\", inode)\n\t\t}\n\n\t\tif err = doCompact(inode, path, uint16(coCnt)); err != nil {\n\t\t\tlogger.Error(err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc doCompact(inode meta.Ino, path string, coCnt uint16) error {\n\tf, err := openController(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"open control file for [%d:%s]: %w\", inode, path, err)\n\t}\n\tdefer f.Close()\n\n\theaderLen, bodyLen := uint32(8), uint32(8+2)\n\twb := utils.NewBuffer(headerLen + bodyLen)\n\twb.Put32(meta.CompactPath)\n\twb.Put32(bodyLen)\n\twb.Put64(uint64(inode))\n\twb.Put16(coCnt)\n\n\t_, err = f.Write(wb.Bytes())\n\tif err != nil {\n\t\tlogger.Fatalf(\"write message: %s\", err)\n\t}\n\n\tprogress := utils.NewProgress(false)\n\tbar := progress.AddCountBar(\"Compacted chunks\", 0)\n\t_, errno := readProgress(f, func(totalChunks, currChunks uint64) {","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/cmd/compact.go#L75-L111","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\njuicefs compact /tmp/data  # open control file for [2:/tmp/data]: ...\n// after\njuicefs mount redis://127.0.0.1:6379/1 /mnt/jfs\njuicefs compact /mnt/jfs/data","handlingStrategy":"try-catch","validationCode":"ctrl := filepath.Join(mountpoint, \".control\")\nif _, err := os.OpenFile(ctrl, os.O_WRONLY, 0); err != nil {\n    return fmt.Errorf(\"control file %s not writable: %w\", ctrl, err)\n}","typeGuard":null,"tryCatchPattern":"if err := runCompact(path); strings.Contains(err.Error(), \"open control file for\") {\n    remount(mountpoint); err = runCompact(path)\n}","preventionTips":["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"],"tags":["cli","fuse","control-file","mount-point"],"backgroundTag":"file-open-failed","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}