{"record":{"id":"9372560fad13762e","repo":"janhq/jan","slug":"settings-general-couldnotrelocatetoroot","errorCode":"settings:general.couldNotRelocateToRoot","errorMessage":"settings:general.couldNotRelocateToRoot","messagePattern":"settings:general\\.couldNotRelocateToRoot","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"web-app/src/routes/settings/general.tsx","lineNumber":128,"sourceCode":"    })\n\n    if (selectedPath === janDataFolder) return\n    if (selectedPath !== null) {\n      setSelectedNewPath(selectedPath as string)\n      setIsDialogOpen(true)\n    }\n  }\n\n  const confirmDataFolderChange = async () => {\n    if (selectedNewPath) {\n      try {\n        await serviceHub.models().stopAllModels()\n        serviceHub.events().emit(SystemEvent.KILL_SIDECAR)\n        setTimeout(async () => {\n          try {\n            // Prevent relocating to root directory (e.g., C:\\ or D:\\ on Windows, / on Unix)\n            if (isRootDir(selectedNewPath))\n              throw new Error(t('settings:general.couldNotRelocateToRoot'))\n            await serviceHub.app().relocateJanDataFolder(selectedNewPath)\n            setJanDataFolder(selectedNewPath)\n            // Only relaunch if relocation was successful\n            window.core?.api?.relaunch()\n            setSelectedNewPath(null)\n            setIsDialogOpen(false)\n          } catch (error) {\n            console.error(error)\n            toast.error(\n              error instanceof Error\n                ? error.message\n                : t('settings:general.failedToRelocateDataFolder')\n            )\n          }\n        }, 1000)\n      } catch (error) {\n        console.error('Failed to relocate data folder:', error)\n        // Revert the data folder path on error","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/janhq/jan/blob/7205d770c1e097c3daf35a911176410e93bc5564/web-app/src/routes/settings/general.tsx#L110-L146","documentation":"During data folder relocation, confirmDataFolderChange blocks moving the data directory to a filesystem root (e.g. C:\\, D:\\, /). It throws an i18n-keyed error because relocating an app's data into the root would scatter/mix files at the filesystem root.","triggerScenarios":"User picks a drive root or '/' as the new Jan data folder in Settings > General and confirms the change.","commonSituations":"User selects a whole drive letter in the folder picker on Windows, or navigates to '/' on Unix, then confirms relocation.","solutions":["Choose a non-root subdirectory as the new data folder (e.g. D:\\JanData or /home/user/jan)","Create a dedicated folder before relocating","Update the UI validation to pre-filter root directories in the picker"],"exampleFix":"// before\nif (isRootDir(selectedNewPath))\n  throw new Error(t('settings:general.couldNotRelocateToRoot'))\n// after\nconst target = selectedNewPath.replace(/[\\\\/]+$/, '')\nif (isRootDir(target))\n  throw new Error(t('settings:general.couldNotRelocateToRoot'))\nawait serviceHub.app().relocateJanDataFolder(target)","handlingStrategy":"validation","validationCode":"if (isRootDir(selectedNewPath)) { showError(t('settings:general.couldNotRelocateToRoot')); return }","typeGuard":"function isSafeTarget(p: string): boolean { return !!p && !isRootDir(p) }","tryCatchPattern":"try { await confirmDataFolderChange() } catch (e) { dialog.showError(t('settings:general.couldNotRelocateToRoot')) }","preventionTips":["Disable root directories in the folder picker UI","Normalize trailing separators before root checks","Confirm dialog copy explains why root paths are rejected"],"tags":["filesystem","validation","settings"],"backgroundTag":"invalid-config-value","analyzedSha":"7205d770c1e097c3daf35a911176410e93bc5564","analyzedAt":"2026-09-17T14:27:30.100Z","contentChangedAt":"2026-09-17T14:27:30.100Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}