parcel-bundler/parcel · error · Error

Cannot call getCode() on an asset with a dirty AST. For tran

Error message

Cannot call getCode() on an asset with a dirty AST. For transformers, implement canReuseAST() and check asset.isASTDirty.

What it means

`getCode()` returns the asset's source. If the asset has an AST that has been modified (`isASTDirty === true`), reading `getCode()` would return stale code that doesn't reflect the AST changes. Parcel refuses to serve inconsistent data and instructs the transformer to either regenerate from the AST or declare it reusable.

Source

Thrown at packages/core/core/src/UncommittedAsset.js:164

      return {size, hash: hash.finish()};
    }

    let hash;
    if (typeof content === 'string') {
      hash = hashString(content);
      size = Buffer.byteLength(content);
    } else {
      hash = hashBuffer(content);
      size = content.length;
    }

    await this.options.cache.setBlob(contentKey, content);
    return {size, hash};
  }

  async getCode(): Promise<string> {
    if (this.ast != null && this.isASTDirty) {
      throw new Error(
        'Cannot call getCode() on an asset with a dirty AST. For transformers, implement canReuseAST() and check asset.isASTDirty.',
      );
    }

    let content = await this.content;
    if (typeof content === 'string' || content instanceof Buffer) {
      return content.toString();
    } else if (content != null) {
      this.content = bufferStream(content);
      return (await this.content).toString();
    }

    invariant(false, 'Internal error: missing content');
  }

  async getBuffer(): Promise<Buffer> {
    let content = await this.content;
    if (content == null) {

View on GitHub (pinned to 59484858a1)

Solutions

  1. Implement `canReuseAST()` and check `asset.isASTDirty` before touching the AST.
  2. Regenerate code from the AST (via `generate`) before calling `getCode()`.
  3. If you only need code, avoid mutating the AST, or set `ast` to null after extracting code.

Example fix

// before
asset.ast = transform(ast);
const code = await asset.getCode(); // throws

// after
asset.ast = transform(ast);
const {content} = await generate({asset, ast: asset.ast, options});
const code = content;
Defensive patterns

Strategy: validation

Validate before calling

// Do not read code while the AST is dirty.
if (asset.ast != null && asset.isASTDirty) {
  await regenerateFromAST(asset);
}
const code = await asset.getCode();

Type guard

function isASTClean(asset: {ast?: mixed, isASTDirty: boolean}): boolean {
  return asset.ast == null || asset.isASTDirty === false;
}

Prevention

When it happens

Trigger: A transformer mutates `asset.ast` (marking it dirty) and then calls `asset.getCode()` before the AST has been regenerated.

Common situations: Custom transformers that edit the AST and then try to read the original source string; calling getCode in `postProcess` after AST mutation.

Related errors


AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13). Data as JSON: /api/errors/e520a0df2bee8ae4. Report an issue: GitHub.