ReactiveX/rxjs · critical · TypeError

Cannot initialize @rxjs/observable-polyfill: ${label} is not

Error message

Cannot initialize @rxjs/observable-polyfill: ${label} is not writable or configurable

What it means

During polyfill initialization, preparePropertyInstallation checks whether each global property it must install (Observable, Symbol.observable, Subscriber, etc.) can be safely defined: an existing property is overridable only if it is configurable and (writable or has a writable setter). If a previous occupant of the global is locked down (non-configurable and non-writable), initialization throws this TypeError naming the label that could not be installed.

Source

Thrown at packages/observable-polyfill/src/index.ts:1327

    typeof value === 'object' &&
    value !== null &&
    typeof (value as Partial<ObservablePolyfillInfo>).packageName === 'string' &&
    typeof (value as Partial<ObservablePolyfillInfo>).version === 'string'
  );
}

interface PropertyInstallation {
  readonly key: PropertyKey;
  readonly label: string;
  readonly next: PropertyDescriptor;
  readonly previous: PropertyDescriptor | undefined;
  readonly target: object;
}

function preparePropertyInstallation(target: object, key: PropertyKey, next: PropertyDescriptor, label: string): PropertyInstallation {
  const previous = Object.getOwnPropertyDescriptor(target, key);
  if (!canDefineProperty(target, previous, next)) {
    throw new TypeError(`Cannot initialize @rxjs/observable-polyfill: ${label} is not writable or configurable`);
  }
  return { key, label, next, previous, target };
}

function canDefineProperty(target: object, previous: PropertyDescriptor | undefined, next: PropertyDescriptor): boolean {
  if (!previous) {
    return Object.isExtensible(target);
  }
  if (previous.configurable) {
    return true;
  }
  if ('value' in previous && 'value' in next && previous.writable) {
    return next.configurable === false && next.enumerable === previous.enumerable && next.writable !== false;
  }
  return false;
}

function installPropertiesAtomically(installations: PropertyInstallation[]): void {

View on GitHub (pinned to 54796b38a5)

Solutions

  1. Don't freeze/lock the target global before importing the polyfill; make any pre-existing property configurable (configurable: true) or delete it first.
  2. If a conforming native Observable already exists, ensure the polyfill's selection logic uses it rather than redefining (check for duplicate installs of the polyfill in the bundle).
  3. Dedupe the package (add resolutions/overrides so only one copy of @rxjs/observable-polyfill is bundled).
  4. In locked-down environments, install the polyfill's exports onto local scope rather than globals, or run initialization before lockdown (e.g. before SES lockdown()).

Example fix

// before
Object.defineProperty(globalThis, 'Observable', { value: MyObs, writable: false, configurable: false });
import '@rxjs/observable-polyfill'; // throws
// after
import '@rxjs/observable-polyfill'; // install first
// or keep the property overridable:
Object.defineProperty(globalThis, 'Observable', { value: MyObs, writable: true, configurable: true });
Defensive patterns

Strategy: validation

Validate before calling

const desc = Object.getOwnPropertyDescriptor(globalThis, 'Observable');
if (desc && (!desc.configurable && desc.writable === false)) {
  // do not import the polyfill globals; use module exports directly
}

Type guard

function canInstallGlobal(key: PropertyKey): boolean {
  const d = Object.getOwnPropertyDescriptor(globalThis, key);
  return !d || d.configurable || !!d.writable || !!d.set;
}

Prevention

When it happens

Trigger: Importing @rxjs/observable-polyfill in an environment where the target global (e.g. Observable on globalThis) already exists as a non-writable, non-configurable property — e.g. after Object.defineProperty(globalThis, 'Observable', { value: X, writable: false, configurable: false }), or after Object.freeze(globalThis), or a security-hardened/locked-down realm (SES, LavaMoat, snow), or duplicate/conflicting polyfill installs.

Common situations: Content-security hardening (frozen globals), sandboxed plugin systems, embedded contexts (VS Code webviews, Salesforce LWC), bundlers double-including the polyfill, another library that installed a frozen Observable first (or a native shim frozen before this module loads).

Related errors


AI-assisted analysis of ReactiveX/rxjs@54796b38a5 (2026-08-28). Data as JSON: /api/errors/d2ebc62a5be232f5. Report an issue: GitHub.