{"record":{"id":"94b5e3a0ede85e63","repo":"lima-vm/lima","slug":"failed-to-symlink-q-to-q-w","errorCode":null,"errorMessage":"failed to symlink %#q to %#q: %w","messagePattern":"failed to symlink %#q to %#q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/driverutil/disk.go","lineNumber":37,"sourceCode":"\t\"github.com/lima-vm/lima/v2/pkg/iso9660util\"\n\t\"github.com/lima-vm/lima/v2/pkg/limatype/filenames\"\n\t\"github.com/lima-vm/lima/v2/pkg/osutil\"\n)\n\n// MigrateDiskLayout creates symlinks from the current filenames (disk, iso) to\n// the legacy filenames (diffdisk, basedisk) used by older Lima versions.\n// The original files are left in place so older Lima versions can still use them.\nfunc MigrateDiskLayout(instDir string) error {\n\tdiskPath := filepath.Join(instDir, filenames.Disk)\n\tif osutil.FileExists(diskPath) {\n\t\treturn nil // already migrated or new instance\n\t}\n\n\tdiffDiskPath := filepath.Join(instDir, filenames.DiffDiskLegacy)\n\tif osutil.FileExists(diffDiskPath) {\n\t\tlogrus.Infof(\"Creating symlink %#q -> %#q\", filenames.Disk, filenames.DiffDiskLegacy)\n\t\tif err := os.Symlink(filenames.DiffDiskLegacy, diskPath); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to symlink %#q to %#q: %w\", filenames.Disk, filenames.DiffDiskLegacy, err)\n\t\t}\n\t}\n\n\tbaseDiskPath := filepath.Join(instDir, filenames.BaseDiskLegacy)\n\tisoPath := filepath.Join(instDir, filenames.ISO)\n\tif osutil.FileExists(baseDiskPath) && !osutil.FileExists(isoPath) {\n\t\tisISO, err := iso9660util.IsISO9660(baseDiskPath)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif isISO {\n\t\t\tlogrus.Infof(\"Creating symlink %#q -> %#q\", filenames.ISO, filenames.BaseDiskLegacy)\n\t\t\tif err := os.Symlink(filenames.BaseDiskLegacy, isoPath); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to symlink %#q to %#q: %w\", filenames.ISO, filenames.BaseDiskLegacy, err)\n\t\t\t}\n\t\t}\n\t\t// Non-ISO basedisk is a legacy qcow2 backing file; leave it for QEMU to resolve.\n\t}","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/driverutil/disk.go#L19-L55","documentation":"During migration of the legacy per-instance disk layout, the driver tries to create a symlink from the legacy diffdisk filename to the new disk filename. If os.Symlink fails (permissions, existing file, cross-device, no symlink support), the error is wrapped and returned, aborting migration and instance start.","triggerScenarios":"MigrateDiskLayout (called from Prepare) finds <instDir>/diffdisk present and attempts os.Symlink(\"diffdisk\", <instDir>/disk); the symlink call fails, e.g. because 'disk' already exists, the directory is read-only, or the filesystem does not allow symlinks (common on Windows without privileges).","commonSituations":"Starting an instance created by an older Lima version after a partially failed migration; running on Windows/FAT filesystems lacking symlink support; leftover files from a crashed run.","solutions":["Inspect the wrapped cause; if 'disk' already exists, remove the stale target and retry","Fix directory permissions on the instance directory under LIMA_HOME","Pre-migrate manually: delete stray 'disk' file, then `ln -s diffdisk disk` inside the instance dir","If symlinks are unsupported on the volume, move LIMA_HOME to an NTFS/native-symlink-capable volume"],"exampleFix":"# before (in instance dir)\n$ limactl start inst  # fails: failed to symlink \"disk\" to \"diffdisk\": file exists\n# after\n$ rm inst/disk && ln -s diffdisk inst/disk && limactl start inst","handlingStrategy":"try-catch","validationCode":"func canMigrate(instDir string) error {\n\tif _, err := os.Lstat(filepath.Join(instDir, \"disk\")); err == nil {\n\t\treturn fmt.Errorf(\"stale 'disk' file exists in %s\", instDir)\n\t}\n\treturn os.accessCheckWritable(instDir) // ensure writable, symlink-capable fs\n}","typeGuard":"func symlinkSupported(dir string) bool {\n\tt := filepath.Join(dir, \".lima-link-test\")\n\tif err := os.Symlink(\"target\", t); err != nil { return false }\n\t_ = os.Remove(t)\n\treturn true\n}","tryCatchPattern":"if err := driverutil.MigrateDiskLayout(instDir); err != nil {\n\tvar pe *fs.PathError\n\tif errors.As(err, &pe) && errors.Is(pe.Err, syscall.EEXIST) {\n\t\tos.Remove(filepath.Join(instDir, \"disk\"))\n\t\treturn driverutil.MigrateDiskLayout(instDir)\n\t}\n\treturn err\n}","preventionTips":["Keep LIMA_HOME on a local filesystem that supports symlinks (NTFS on Windows, not network shares)","Do not pre-create files named disk/iso/basedisk/diffdisk in instance dirs","Back up instance dirs before upgrading Lima versions"],"tags":["symlink","disk-layout","migration","instance-storage"],"backgroundTag":"symlink-creation-failed","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}