{"record":{"id":"8d3e5c2329ad310c","repo":"microsoft/monaco-editor","slug":"the-script-at-createdata-customworkerpath-does","errorCode":null,"errorMessage":"The script at ${createData.customWorkerPath} does not add customTSWorkerFactory to self","messagePattern":"The script at (.+?) does not add customTSWorkerFactory to self","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/languages/features/typescript/tsWorker.ts","lineNumber":511,"sourceCode":"\ndeclare global {\n\tvar importScripts: (path: string) => void | undefined;\n\tvar customTSWorkerFactory: CustomTSWebWorkerFactory | undefined;\n}\n\nexport function create(ctx: worker.IWorkerContext, createData: ICreateData): TypeScriptWorker {\n\tlet TSWorkerClass = TypeScriptWorker;\n\tif (createData.customWorkerPath) {\n\t\tif (typeof importScripts === 'undefined') {\n\t\t\tconsole.warn(\n\t\t\t\t'Monaco is not using webworkers for background tasks, and that is needed to support the customWorkerPath flag'\n\t\t\t);\n\t\t} else {\n\t\t\tself.importScripts(createData.customWorkerPath);\n\n\t\t\tconst workerFactoryFunc: CustomTSWebWorkerFactory | undefined = self.customTSWorkerFactory;\n\t\t\tif (!workerFactoryFunc) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The script at ${createData.customWorkerPath} does not add customTSWorkerFactory to self`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tTSWorkerClass = workerFactoryFunc(TypeScriptWorker, ts, libFileMap);\n\t\t}\n\t}\n\n\treturn new TSWorkerClass(ctx, createData);\n}\n\n/** Allows for clients to have access to the same version of TypeScript that the worker uses */\n// @ts-ignore\nglobalThis.ts = ts.typescript;\n","sourceCodeStart":493,"sourceCodeEnd":526,"githubUrl":"https://github.com/microsoft/monaco-editor/blob/ca1b42dc896b99db78e1c743256e8654e12cea2d/src/languages/features/typescript/tsWorker.ts#L493-L526","documentation":"Thrown by the TypeScript worker's create() when createData.customWorkerPath is set, the script at that path was imported via self.importScripts, but the script did not assign self.customTSWorkerFactory. The customWorkerPath mechanism lets users swap the TypeScript worker class (e.g. to add extra lib files or hook tsserver) by loading a script that defines a factory on the global scope. If the script runs but doesn't register the factory, the worker cannot proceed and throws. The factory signature is (TypeScriptWorker, ts, libFileMap) => typeof TypeScriptWorker.","triggerScenarios":"Setting monaco.languages.typescript.typescriptDefaults.setWorkerOptions({ customWorkerPath: './my-ts-worker.js' }) where my-ts-worker.js exists and loads but does not execute `self.customTSWorkerFactory = ...`; the script threw before reaching the assignment; the script assigns under a different global name.","commonSituations":"Custom worker script has a syntax/runtime error that aborts before the assignment; author forgot the `self.customTSWorkerFactory =` line; the path points to a script that exports via module syntax instead of assigning to self; bundling the custom worker stripped the global assignment.","solutions":["Ensure the script at customWorkerPath ends with `self.customTSWorkerFactory = (TypeScriptWorker, ts, libFileMap) => class extends TypeScriptWorker { /* overrides */ }`.","Open the custom worker script's console — if it threw before the assignment, fix that error first.","Confirm customWorkerPath is a URL resolvable from the worker scope and that importScripts actually loaded it (a 404 means the assignment never runs).","If you bundled the custom worker, make sure the bundler did not rename/rewrite the `self.customTSWorkerFactory =` assignment or wrap it in a module scope where `self` is shadowed.","Verify the factory returns a class extending TypeScriptWorker (correct arity and return type)."],"exampleFix":"// before — my-ts-worker.js exports via module syntax, never assigns self\nexport class MyWorker extends TypeScriptWorker {}\n// after\nself.customTSWorkerFactory = (TypeScriptWorker, ts, libFileMap) => {\n  return class MyWorker extends TypeScriptWorker {\n    // custom overrides here\n  };\n};","handlingStrategy":"validation","validationCode":"// before enabling customWorkerPath, verify the script assigns the global\n// (open the script URL in a worker and check self.customTSWorkerFactory)\n// example minimal correct script body:\n//   self.customTSWorkerFactory = (Base, ts, libs) => class extends Base {};\ntypescriptDefaults.setWorkerOptions({ customWorkerPath: '/assets/my-ts-worker.js' });","typeGuard":"function scriptRegistersFactory(): boolean {\n  // only meaningful inside a worker after importScripts\n  return typeof (self as any).customTSWorkerFactory === 'function';\n}","tryCatchPattern":"try {\n  await loadMonacoAndUseTSWorker();\n} catch (e) {\n  if (e instanceof Error && /customTSWorkerFactory/.test(e.message)) {\n    console.error('The customWorkerPath script must assign self.customTSWorkerFactory.');\n  }\n  throw e;\n}","preventionTips":["End every custom worker script with an explicit `self.customTSWorkerFactory = ...` assignment.","Verify the script is reachable from the worker origin (no 404) and has no syntax errors.","Avoid bundlers that scope `self` or strip global assignments; build the custom worker as an IIFE that writes to self."],"tags":["runtime","typescript","web-worker","custom-worker","language-services"],"backgroundTag":null,"analyzedSha":"ca1b42dc896b99db78e1c743256e8654e12cea2d","analyzedAt":"2026-08-13T02:00:51.380Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}