{"record":{"id":"cc4def4bc9cb9c59","repo":"lima-vm/lima","slug":"failed-to-run-attach-disk-q-in-use-by-instance","errorCode":null,"errorMessage":"failed to run attach disk %#q, in use by instance %#q","messagePattern":"failed to run attach disk %#q, in use by instance %#q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/driver/krunkit/krunkit_darwin_arm64.go","lineNumber":69,"sourceCode":"\t\t\"--device\", fmt.Sprintf(\"virtio-vsock,port=%d,socketURL=%s,connect\", vSockPort, filepath.Join(inst.Dir, filenames.GuestAgentSock)),\n\t}\n\n\tif inst.Config.SSH.OverVsock != nil && *inst.Config.SSH.OverVsock {\n\t\tsshVsockPath := filepath.Join(inst.Dir, sshVsockSock)\n\t\targs = append(args, \"--device\", fmt.Sprintf(\"virtio-vsock,port=22,socketURL=%s,connect\", sshVsockPath))\n\t}\n\n\t// Add additional disks\n\tif len(inst.Config.AdditionalDisks) > 0 {\n\t\tctx := context.Background()\n\t\tdiskUtil := proxyimgutil.NewDiskUtil(ctx)\n\t\tfor _, d := range inst.Config.AdditionalDisks {\n\t\t\tdisk, derr := store.InspectDisk(d.Name, d.FSType)\n\t\t\tif derr != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to load disk %#q: %w\", d.Name, derr)\n\t\t\t}\n\t\t\tif disk.Instance != \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to run attach disk %#q, in use by instance %#q\", disk.Name, disk.Instance)\n\t\t\t}\n\t\t\tif lerr := disk.Lock(inst.Dir); lerr != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to lock disk %#q: %w\", d.Name, lerr)\n\t\t\t}\n\t\t\textraDiskPath := filepath.Join(disk.Dir, filenames.DataDisk)\n\t\t\tlogrus.Infof(\"Mounting disk %#q on %#q\", disk.Name, disk.MountPoint)\n\t\t\tif cerr := diskUtil.Convert(ctx, raw.Type, extraDiskPath, extraDiskPath, nil, true); cerr != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to convert extra disk %#q to raw: %w\", extraDiskPath, cerr)\n\t\t\t}\n\t\t\targs = append(args, \"--device\", fmt.Sprintf(\"virtio-blk,path=%s,format=raw\", extraDiskPath))\n\t\t}\n\t}\n\n\t// Network commands\n\tnetworkArgs, err := buildNetworkArgs(inst)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to build network arguments: %w\", err)\n\t}","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/driver/krunkit/krunkit_darwin_arm64.go#L51-L87","documentation":"Cmdline checks each additional disk's `disk.Instance` field; if it is non-empty the disk is already attached to another running Lima instance, so krunkit refuses to attach it a second time and returns `failed to run attach disk %#q, in use by instance <name>`. Lima disks are single-attach: locking to more than one instance would corrupt data.","triggerScenarios":"Starting an instance whose `additionalDisks` includes a disk whose metadata records it as in use by a different (usually still registered as running) instance; happens when a previous instance crashed without releasing the disk or two instances reference the same disk.","commonSituations":"Cloning an instance config that shares `additionalDisks` between instances; a previous VM crashed leaving the disk lock/instance field stale; trying to boot the same disk in a second instance for parallel workloads.","solutions":["Stop/ungister the instance currently holding the disk (`limactl stop <other-instance>`), then start yours.","If the holder instance is stale/gone, remove the stale reference: `limactl disk undeploy <disk>` (or delete disk metadata) so it can be re-attached.","Give each instance its own disk: create a new disk with `limactl disk create` and update `additionalDisks`.","Run `limactl disk list` to see which instance occupies the disk before starting."],"exampleFix":"# before (second instance lima.yaml)\nadditionalDisks:\n  - name: shared-data   # attached to instance \"dev\"\n# after\nadditionalDisks:\n  - name: shared-data-2 # limactl disk create shared-data-2 --size 50G","handlingStrategy":"validation","validationCode":"// Go: check the disk is free before start\nif diskJSON, err := exec.Command(\"limactl\", \"disk\", \"list\", diskName).Output(); err == nil {\n    if bytes.Contains(diskJSON, []byte(\"instance:\")) && !bytes.Contains(diskJSON, []byte(\"instance: \\\"\\\"\")) {\n        return fmt.Errorf(\"disk %q in use; stop the holder instance first\", diskName)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := startInstance(ctx, name); err != nil {\n    if strings.Contains(err.Error(), \"in use by instance\") {\n        holder := extractInstanceName(err.Error())\n        _ = exec.Command(\"limactl\", \"stop\", holder).Run()\n        return startInstance(ctx, name) // retry once\n    }\n    return err\n}","preventionTips":["Never share additionalDisks between concurrently running instances","Run `limactl disk list` to inspect attachment before start","After crashes, run `limactl disk undeploy <disk>` to clear stale attachment","Give each parallel instance its own disk"],"tags":["krunkit","disks","lock","macos","concurrency"],"backgroundTag":"disk-already-in-use","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}