{"record":{"id":"23f4b3f2c78234c0","repo":"siyuan-note/siyuan","slug":"stat-destination-s-failed-w","errorCode":null,"errorMessage":"stat destination [%s] failed: %w","messagePattern":"stat destination \\[(.+?)\\] failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/working_mobile.go","lineNumber":188,"sourceCode":"\tif 0 < len(destinationEntries) {\n\t\treturn false, fmt.Errorf(\"destination [%s] is not empty\", defaultWorkspaceDir)\n\t}\n\n\tvar moves []workspaceDirMove\n\tfor _, name := range legacyIOSWorkspaceEntries {\n\t\tfrom := filepath.Join(workspaceBaseDir, name)\n\t\tif _, statErr := os.Lstat(from); statErr != nil {\n\t\t\tif errors.Is(statErr, fs.ErrNotExist) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn false, fmt.Errorf(\"stat source [%s] failed: %w\", from, statErr)\n\t\t}\n\n\t\tto := filepath.Join(defaultWorkspaceDir, name)\n\t\tif _, statErr := os.Lstat(to); statErr == nil {\n\t\t\treturn false, fmt.Errorf(\"destination [%s] already exists\", to)\n\t\t} else if !errors.Is(statErr, fs.ErrNotExist) {\n\t\t\treturn false, fmt.Errorf(\"stat destination [%s] failed: %w\", to, statErr)\n\t\t}\n\t\tmoves = append(moves, workspaceDirMove{from: from, to: to})\n\t}\n\n\tvar completed []workspaceDirMove\n\tfor _, move := range moves {\n\t\tif renameErr := os.Rename(move.from, move.to); renameErr != nil {\n\t\t\tvar rollbackErrors []error\n\t\t\tfor i := len(completed) - 1; 0 <= i; i-- {\n\t\t\t\tcompletedMove := completed[i]\n\t\t\t\tif rollbackErr := os.Rename(completedMove.to, completedMove.from); rollbackErr != nil {\n\t\t\t\t\trollbackErrors = append(rollbackErrors, fmt.Errorf(\"rollback [%s] to [%s] failed: %w\",\n\t\t\t\t\t\tcompletedMove.to, completedMove.from, rollbackErr))\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false, errors.Join(append([]error{fmt.Errorf(\"move [%s] to [%s] failed: %w\", move.from, move.to, renameErr)}, rollbackErrors...)...)\n\t\t}\n\t\tcompleted = append(completed, move)","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/util/working_mobile.go#L170-L206","documentation":"While pre-checking moves, os.Lstat on a destination path inside <base>/siyuan returned an error other than fs.ErrNotExist (i.e. not a clean 'does not exist' answer). Migration aborts because the existence check itself failed, so it cannot guarantee a safe rename.","triggerScenarios":"migrateLegacyIOSWorkspace's destination Lstat hits EACCES/EIO or similar on <base>/siyuan/<name> after the destination ReadDir already succeeded.","commonSituations":"Race with another process creating/removing files in the destination concurrently; transient I/O errors; permission changes mid-run; filesystem corruption on the device.","solutions":["Inspect the wrapped %w error to distinguish permission vs I/O vs transient causes","Ensure no other SiYuan instance or sync process is writing to the workspace during migration; restart and retry","Fix destination directory permissions so Lstat can complete","If persistent, verify device storage health / reinstall the app to recreate a clean container"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Go: confirm destination directory is stat-able and stable before migrating\ndest := filepath.Join(base, \"siyuan\")\nif fi, err := os.Stat(dest); err != nil || !fi.IsDir() {\n    return fmt.Errorf(\"destination %s not a usable directory\", dest)\n}","typeGuard":null,"tryCatchPattern":"// Go\nfor attempt := 0; attempt < 3; attempt++ {\n    migrated, err := migrateLegacyIOSWorkspace(base)\n    if err == nil { break }\n    if !strings.Contains(err.Error(), \"stat destination\") { return err }\n    time.Sleep(200 * time.Millisecond) // transient concurrent-access failure\n}","preventionTips":["Ensure only one SiYuan instance touches the workspace during migration","Disable sync clients while migration runs","Reboot once if I/O errors persist - they often indicate a transient kernel/filesystem issue"],"tags":["go","filesystem","ios","migration","stat"],"backgroundTag":"file-read-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}