angular/angular-cli · info

[NG HMR] Cannot restore selected options.

Error message

[NG HMR] Cannot restore selected options.

What it means

A console.warn from the Angular CLI HMR helper meaning selected <option> states could not be restored after a hot reload. Like inputs, options are restored only when the count of new <option> elements equals the count captured before the update; otherwise the warning fires and select selections are lost.

Source

Thrown at packages/angular_devkit/build_angular/src/tools/webpack/plugins/hmr/hmr-accept.ts:240

      dispatchEvents(newElement);
    }
  } else if (oldInputs.length) {
    console.warn('[NG HMR] Cannot restore input/textarea values.');
  }

  // Restore option
  const newOptions = document.querySelectorAll('option');
  if (newOptions.length && newOptions.length === oldOptions.length) {
    console.log('[NG HMR] Restoring selected options.');
    for (let index = 0; index < newOptions.length; index++) {
      const newElement = newOptions[index];
      newElement.selected = oldOptions[index].selected;

      dispatchEvents(newElement);
    }
  } else if (oldOptions.length) {
    console.warn('[NG HMR] Cannot restore selected options.');
  }
}

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Re-select the value after HMR (form controls bound with reactive forms or ngModel usually restore the selection automatically once the model rebinds).
  2. Keep option lists stable across the edit, or drive selection from component state so it re-applies on the new DOM.
  3. Persist selection state (service/localStorage) and reapply after the update if options are dynamic.
  4. Disable HMR (--no-hmr) on pages where select state loss matters.

Example fix

// before (template-driven options, selection lost)
<option *ngFor="let o of opts">{{o}}</option>
// after (reactive binding restores value)
<select [formControl]="sel"><option *ngFor="let o of opts" [value]="o">{{o}}</option></select>
Defensive patterns

Strategy: fallback

Validate before calling

const oldCount = document.querySelectorAll('option').length;
// after HMR update:
if (document.querySelectorAll('option').length !== oldCount) {
  console.info('Option count changed; selections will not be restored by HMR.');
}

Type guard

function canRestoreOptions(oldLen: number, newLen: number): boolean {
  return oldLen > 0 && oldLen === newLen;
}

Prevention

When it happens

Trigger: During restoreFormValues: oldOptions.length > 0 but newOptions.length !== oldOptions.length — the update changed the number of <option> elements in any select on the page (options added/removed), or new options were not yet rendered when restore ran.

Common situations: HMR update touches a component with a select whose options are generated dynamically (*ngFor over data that changed); options conditionally rendered; page contains multiple selects with option counts that differ after the update; async-loaded option lists not populated yet at restore time.

Related errors


AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30). Data as JSON: /api/errors/5272f004667f578a. Report an issue: GitHub.