microsoft/monaco-editor · error · Error

The script at ${createData.customWorkerPath} does not add cu

Error message

The script at ${createData.customWorkerPath} does not add customTSWorkerFactory to self

What it means

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.

Source

Thrown at src/languages/features/typescript/tsWorker.ts:511

declare global {
	var importScripts: (path: string) => void | undefined;
	var customTSWorkerFactory: CustomTSWebWorkerFactory | undefined;
}

export function create(ctx: worker.IWorkerContext, createData: ICreateData): TypeScriptWorker {
	let TSWorkerClass = TypeScriptWorker;
	if (createData.customWorkerPath) {
		if (typeof importScripts === 'undefined') {
			console.warn(
				'Monaco is not using webworkers for background tasks, and that is needed to support the customWorkerPath flag'
			);
		} else {
			self.importScripts(createData.customWorkerPath);

			const workerFactoryFunc: CustomTSWebWorkerFactory | undefined = self.customTSWorkerFactory;
			if (!workerFactoryFunc) {
				throw new Error(
					`The script at ${createData.customWorkerPath} does not add customTSWorkerFactory to self`
				);
			}

			TSWorkerClass = workerFactoryFunc(TypeScriptWorker, ts, libFileMap);
		}
	}

	return new TSWorkerClass(ctx, createData);
}

/** Allows for clients to have access to the same version of TypeScript that the worker uses */
// @ts-ignore
globalThis.ts = ts.typescript;

View on GitHub (pinned to ca1b42dc89)

Solutions

  1. Ensure the script at customWorkerPath ends with `self.customTSWorkerFactory = (TypeScriptWorker, ts, libFileMap) => class extends TypeScriptWorker { /* overrides */ }`.
  2. Open the custom worker script's console — if it threw before the assignment, fix that error first.
  3. Confirm customWorkerPath is a URL resolvable from the worker scope and that importScripts actually loaded it (a 404 means the assignment never runs).
  4. 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.
  5. Verify the factory returns a class extending TypeScriptWorker (correct arity and return type).

Example fix

// before — my-ts-worker.js exports via module syntax, never assigns self
export class MyWorker extends TypeScriptWorker {}
// after
self.customTSWorkerFactory = (TypeScriptWorker, ts, libFileMap) => {
  return class MyWorker extends TypeScriptWorker {
    // custom overrides here
  };
};
Defensive patterns

Strategy: validation

Validate before calling

// before enabling customWorkerPath, verify the script assigns the global
// (open the script URL in a worker and check self.customTSWorkerFactory)
// example minimal correct script body:
//   self.customTSWorkerFactory = (Base, ts, libs) => class extends Base {};
typescriptDefaults.setWorkerOptions({ customWorkerPath: '/assets/my-ts-worker.js' });

Type guard

function scriptRegistersFactory(): boolean {
  // only meaningful inside a worker after importScripts
  return typeof (self as any).customTSWorkerFactory === 'function';
}

Try / catch

try {
  await loadMonacoAndUseTSWorker();
} catch (e) {
  if (e instanceof Error && /customTSWorkerFactory/.test(e.message)) {
    console.error('The customWorkerPath script must assign self.customTSWorkerFactory.');
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/monaco-editor@ca1b42dc89 (2026-08-13). Data as JSON: /api/errors/8d3e5c2329ad310c. Report an issue: GitHub.