{"record":{"id":"075febb6165065f0","repo":"siyuan-note/siyuan","slug":"stat-source-s-failed-w","errorCode":null,"errorMessage":"stat source [%s] failed: %w","messagePattern":"stat source \\[(.+?)\\] failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/working_mobile.go","lineNumber":181,"sourceCode":"\t}\n\n\tdefaultWorkspaceDir := filepath.Join(workspaceBaseDir, \"siyuan\")\n\tdestinationEntries, readErr := os.ReadDir(defaultWorkspaceDir)\n\tif readErr != nil {\n\t\treturn false, fmt.Errorf(\"read destination [%s] failed: %w\", defaultWorkspaceDir, readErr)\n\t}\n\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 {","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/util/working_mobile.go#L163-L199","documentation":"While enumerating legacy iOS workspace entries to move, os.Lstat on a source entry failed with an error other than fs.ErrNotExist. Migration aborts because it cannot determine whether the source exists, avoiding destructive assumptions about user data.","triggerScenarios":"migrateLegacyIOSWorkspace calls os.Lstat(<workspaceBaseDir>/<name>) and gets a non-ENOENT error (e.g. EACCES, EIO, or a broken symlink edge).","commonSituations":"Sandbox tightened read permissions on the app container after an OS update; iCloud/offloaded storage making the file inaccessible; filesystem I/O errors on the device.","solutions":["Read the wrapped %w error to identify the syscall failure (permission vs I/O)","Fix container permissions: reinstall the app or reset its sandbox/documents permissions in system settings","For offloaded iCloud files, download them locally so Lstat/stat can access them","Retry after rebooting the device if it is a transient I/O error"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Go: probe access to the legacy directory before migrating\nif _, err := os.ReadDir(workspaceBaseDir); err != nil {\n    return fmt.Errorf(\"legacy base dir not readable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"// Go\nif err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) && !errors.Is(perr.Err, fs.ErrNotExist) {\n        // permission or I/O problem: back off, keep legacy data untouched, surface to user\n        return err\n    }\n}","preventionTips":["Keep legacy workspace entries on local storage (avoid iCloud offloading) before migration","Reset app container permissions after OS upgrades if document access is denied","Never modify permissions of legacy dirs while the app is running"],"tags":["go","filesystem","ios","migration","stat"],"backgroundTag":"permission-denied","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}