{"record":{"id":"559487e93d3ea6c2","repo":"siyuan-note/siyuan","slug":"destination-s-is-not-empty","errorCode":null,"errorMessage":"destination [%s] is not empty","messagePattern":"destination \\[(.+?)\\] is not empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/working_mobile.go","lineNumber":171,"sourceCode":"\nfunc migrateLegacyIOSWorkspace(workspaceBaseDir string) (migrated bool, err error) {\n\tif ContainerIOS != Container || !gulu.File.IsDir(workspaceBaseDir) {\n\t\treturn false, nil\n\t}\n\n\tfor _, name := range []string{\"conf\", \"data\", \"temp\"} {\n\t\tif !gulu.File.IsDir(filepath.Join(workspaceBaseDir, name)) {\n\t\t\treturn false, nil\n\t\t}\n\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}","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/util/working_mobile.go#L153-L189","documentation":"During legacy iOS workspace migration, the destination <workspaceBaseDir>/siyuan must be empty before entries are moved into it. This error is returned when ReadDir succeeds but the directory already contains entries, to avoid overwriting or mixing with an existing workspace.","triggerScenarios":"migrateLegacyIOSWorkspace (via initWorkspaceDirMobile) finds len(destinationEntries) > 0 in <base>/siyuan on a device where the default workspace was already initialized before legacy migration ran.","commonSituations":"User already opened the app once on the new version (creating conf/ etc. in siyuan/) before legacy data migration triggered; partial previous migration left files behind; user manually created content in the default workspace.","solutions":["If the default workspace already has data you want, keep it and manually move needed legacy files yourself instead of migrating","If the default workspace content is disposable, empty <base>/siyuan and restart the app to rerun migration","Check whether a previous migration half-completed (files present but legacy dirs remain); complete the move manually","Ensure migration runs before first workspace initialization on fresh installs so the destination is still empty"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Go: verify the destination is empty before starting migration\ndest := filepath.Join(base, \"siyuan\")\nentries, err := os.ReadDir(dest)\nif err == nil && len(entries) > 0 {\n    return fmt.Errorf(\"aborting migration: destination %s already has %d entries\", dest, len(entries))\n}","typeGuard":null,"tryCatchPattern":"// Go\nmigrated, err := migrateLegacyIOSWorkspace(base)\nif err != nil && strings.Contains(err.Error(), \"is not empty\") {\n    // default workspace already initialized; skip migration and keep current data\n    return nil // or prompt the user to resolve manually\n}","preventionTips":["Run migration as the very first step on a fresh install, before any workspace content is created","Clean up leftovers from previously failed migration attempts before retrying","Never manually pre-populate the default siyuan/ directory on devices with legacy data"],"tags":["go","filesystem","ios","migration","conflict"],"backgroundTag":"file-already-exists","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"}