{"record":{"id":"c396874c49991b21","repo":"lima-vm/lima","slug":"open-disk-w","errorCode":null,"errorMessage":"open disk: %w","messagePattern":"open disk: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apfs/chown.go","lineNumber":68,"sourceCode":"// the APFS container starts (nonzero for GPT-partitioned disks),\n// and the APFS block size.\ntype container struct {\n\tf          *os.File\n\tbaseOffset int64 // byte offset of APFS container within file\n\tblockSize  uint32\n}\n\n// volumeInfo holds resolved volume information.\ntype volumeInfo struct {\n\tomapTreeAddr uint64 // physical address of volume omap B-tree root\n\trootTreeOID  uint64 // virtual OID of filesystem B-tree root\n\tlatestXID    uint64 // transaction ID of the volume superblock\n}\n\nfunc openContainer(path string) (*container, error) {\n\tf, err := os.OpenFile(path, os.O_RDWR, 0)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"open disk: %w\", err)\n\t}\n\tc := &container{f: f}\n\n\thdr := make([]byte, 4096) // minimum APFS block size\n\tif _, err := f.ReadAt(hdr, 0); err != nil {\n\t\tf.Close()\n\t\treturn nil, fmt.Errorf(\"read block 0: %w\", err)\n\t}\n\n\tif le.Uint32(hdr[nxMagicOff:]) == nxMagic {\n\t\t// Raw APFS container (no partition table).\n\t\tc.blockSize = le.Uint32(hdr[nxBlockSizeOff:])\n\t} else {\n\t\t// Look for a GPT partition table and find the APFS partition.\n\t\toffset, err := findAPFSPartitionGPT(f)\n\t\tif err != nil {\n\t\t\tf.Close()\n\t\t\treturn nil, fmt.Errorf(\"finding APFS partition: %w\", err)","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/apfs/chown.go#L50-L86","documentation":"Thrown by openContainer (invoked at the start of every apfs.Chown call) when os.OpenFile(path, os.O_RDWR, 0) cannot open the disk image. The underlying *os.PathError (ENOENT, EACCES, EISDIR, EMFILE, ...) is wrapped as \"open disk\". Chown requires read-write access because it patches inode blocks in place.","triggerScenarios":"apfs.Chown called with a diskPath that does not exist, is a directory, or the process lacks read/write permission; too many open files in the process.","commonSituations":"Typo in the disk image path; running without sudo on a disk image owned by root (e.g. a macOS system volume); passing a block device that requires elevated privileges; passing the mount point instead of the image/device path.","solutions":["Verify the diskPath exists and is the actual image/device file, not a directory or mount point.","Run with sufficient privileges (e.g. sudo) if the image is root-owned or is a protected block device.","Fix file permissions (chmod/chown) so the current user can open the file read-write.","Check ulimit -n if you suspect file-descriptor exhaustion (EMFILE)."],"exampleFix":"// before\nc, err := apfs.Chown(\"/dev/disk3s1\", ...) // EACCES as non-root\n// after\n// sudo limactl ... (or run the caller with privileges to open the device R/W)","handlingStrategy":"validation","validationCode":"fi, err := os.Stat(diskPath)\nif err != nil {\n    return fmt.Errorf(\"disk %q not found\", diskPath)\n}\nif fi.IsDir() {\n    return fmt.Errorf(\"%q is a directory, expected an image/device\", diskPath)\n}\nif f, err := os.OpenFile(diskPath, os.O_RDWR, 0); err != nil {\n    return fmt.Errorf(\"no read-write access to %q: %w\", diskPath, err)\n} else { f.Close() }","typeGuard":null,"tryCatchPattern":"if err := apfs.Chown(diskPath, role, uid, gid, paths...); err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) && errors.Is(perr, fs.ErrPermission) {\n        // advise running with elevated privileges\n    }\n    return err\n}","preventionTips":["Check existence and writability of the image path before invoking Chown.","Run with the privileges required to open the image/block device read-write.","Pass the image/device path, never a directory or mount point."],"tags":["apfs","filesystem","permissions","io"],"backgroundTag":"permission-denied","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}