{"record":{"id":"775d2d64d79c7ad5","repo":"coder/code-server","slug":"userdatapath-was-not-provided-to-the-browser","errorCode":null,"errorMessage":"userDataPath was not provided to the browser","messagePattern":"userDataPath was not provided to the browser","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"patches/local-storage.diff","lineNumber":58,"sourceCode":"+\treadonly userDataPath?: string\n+\n \t//#endregion\n \n \t//#region Profile options\nIndex: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts\n===================================================================\n--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts\n+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts\n@@ -102,7 +102,14 @@ export class BrowserWorkbenchEnvironment\n \tget logFile(): URI { return joinPath(this.windowLogsPath, 'window.log'); }\n \n \t@memoize\n-\tget userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.vscodeUserData }); }\n+\tget userRoamingDataHome(): URI { return joinPath(URI.file(this.userDataPath).with({ scheme: Schemas.vscodeRemote }), 'User'); }\n+\n+\tget userDataPath(): string {\n+\t\tif (!this.options.userDataPath) {\n+\t\t\tthrow new Error('userDataPath was not provided to the browser');\n+\t\t}\n+\t\treturn this.options.userDataPath;\n+\t}\n \n \t@memoize\n \tget argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }\nIndex: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts\n===================================================================\n--- code-server.orig/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts\n+++ code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts\n@@ -148,8 +148,10 @@ export class WorkspaceService extends Di\n \t\tthis.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService, uriIdentityService, logService));\n \t\tthis._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => {\n \t\t\tthis.onWorkspaceConfigurationChanged(fromCache).then(() => {\n-\t\t\t\tthis.workspace.initialized = this.workspaceConfiguration.initialized;\n-\t\t\t\tthis.checkAndMarkWorkspaceComplete(fromCache);\n+\t\t\t\tif (this.workspace) { // The workspace may not have been created yet.\n+\t\t\t\t\tthis.workspace.initialized = this.workspaceConfiguration.initialized;","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/coder/code-server/blob/51f90a376b42e217b38937410fe2855e0c1db87e/patches/local-storage.diff#L40-L76","documentation":"Thrown by the userDataPath getter added to BrowserWorkbenchEnvironmentImpl by the local-storage.diff patch when this.options.userDataPath is missing. The getter is now depended on by userRoamingDataHome (rewritten by the same patch to join onto userDataPath), so a missing option breaks the entire user-data path resolution and prevents workbench startup.","triggerScenarios":"The workbench construction options do not include userDataPath, but the patched userRoamingDataHome getter now calls this.userDataPath. Any feature resolving user roaming data (settings, argv.json, extensions) trips the throw.","commonSituations":"Applying local-storage.diff without the matching code-server server-side injection of userDataPath; version mismatch where the option name changed; a fork that strips the option but keeps the getter rewrite.","solutions":["Inject userDataPath into the workbench construction options on the code-server side (the absolute user-data directory).","Apply the full local-storage.diff plus the corresponding configurationService.ts hunk so the path resolves consistently.","Rebuild the workbench so the new getter and option are in sync.","Verify the option is non-empty (an empty string is falsy and will also throw)."],"exampleFix":"// server-side option assembly\n// before: no userDataPath\n// after\noptions.userDataPath = req.args['user-data-dir'] || defaultUserDataDir","handlingStrategy":"validation","validationCode":"// Server-side\nif (!options.userDataPath) throw new Error('userDataPath must be configured')\noptions.userDataPath = path.resolve(options.userDataPath)","typeGuard":"function hasUserDataPath(o: Record<string, unknown>): o is { userDataPath: string } {\n  return typeof o.userDataPath === 'string' && o.userDataPath.length > 0\n}","tryCatchPattern":"try {\n  return environmentService.userDataPath\n} catch (e) {\n  if (/userDataPath was not provided/.test(e.message)) throw new Error('Server misconfigured: userDataPath missing')\n}","preventionTips":["Always inject a non-empty userDataPath into construction options.","Apply local-storage.diff as a whole (getter + userRoamingDataHome rewrite + config service hunk).","Add a startup assertion that all patched option getters resolve without throwing.","Rebuild after patching."],"tags":["workbench","patch","environment-service","user-data","config"],"backgroundTag":null,"analyzedSha":"51f90a376b42e217b38937410fe2855e0c1db87e","analyzedAt":"2026-08-12T11:27:34.273Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}