angular/angular-cli · error · Error

compilation is undefined.

Error message

compilation is undefined.

What it means

IndexHtmlWebpackPlugin exposes a lazily-set `compilation` getter that returns the Compilation instance captured during hook execution. Because the plugin stores it privately (_compilation), reading `plugin.compilation` before webpack has applied the plugin throws this error. It signals the getter was accessed outside the plugin's normal apply/hook lifecycle.

Source

Thrown at packages/angular_devkit/build_angular/src/tools/webpack/plugins/index-html-webpack-plugin.ts:32

} from '@angular/build/private';
import { basename, dirname, extname } from 'node:path';
import { Compilation, Compiler, sources } from 'webpack';
import { assertIsError } from '../../../utils/error';
import { addError, addWarning } from '../../../utils/webpack-diagnostics';

export interface IndexHtmlWebpackPluginOptions
  extends IndexHtmlGeneratorOptions,
    Omit<IndexHtmlGeneratorProcessOptions, 'files'> {}

const PLUGIN_NAME = 'index-html-webpack-plugin';
export class IndexHtmlWebpackPlugin extends IndexHtmlGenerator {
  private _compilation: Compilation | undefined;
  get compilation(): Compilation {
    if (this._compilation) {
      return this._compilation;
    }

    throw new Error('compilation is undefined.');
  }

  constructor(override readonly options: IndexHtmlWebpackPluginOptions) {
    super(options);
  }

  apply(compiler: Compiler) {
    compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
      this._compilation = compilation;
      compilation.hooks.processAssets.tapPromise(
        {
          name: PLUGIN_NAME,
          stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE + 1,
        },
        callback,
      );
    });

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Move any code that needs the Compilation into a webpack hook callback (e.g. thisCompilation / emit) where _compilation is guaranteed to be set
  2. Guard the access: check the private _compilation (or wrap the getter call) and handle undefined instead of dereferencing the getter
  3. In tests, run the plugin through a real webpack compilation (webpack(config).run) rather than instantiating it standalone

Example fix

// before
const html = plugin.compilation.assets['index.html'];
// after
compilation.hooks.processAssets.tap({...}, () => {
  const html = plugin.compilation.assets['index.html']; // safe: inside hook
});
Defensive patterns

Strategy: type-guard

Validate before calling

if (plugin['_compilation'] === undefined) {
  throw new Error('access compilation only inside a webpack hook');
}

Type guard

function hasCompilation(p: IndexHtmlWebpackPlugin): p is IndexHtmlWebpackPlugin & { compilation: Compilation } {
  return (p as { _compilation?: Compilation })._compilation !== undefined;
}

Try / catch

let compilation: Compilation | undefined;
try {
  compilation = plugin.compilation;
} catch {
  compilation = undefined; // defer to hook callback
}

Prevention

When it happens

Trigger: Accessing the `compilation` getter of an IndexHtmlWebpackPlugin instance before its `apply()` has run or outside a webpack compiler hook callback (e.g. directly after `new IndexHtmlWebpackPlugin(options)` in unit tests or custom code).

Common situations: Custom tests that instantiate the plugin and inspect `compilation` without running webpack; third-party tooling wrapping the plugin and reading its state too early; refactors that move logic out of the `process` hook into constructor-time code.

Related errors


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