Automattic/mongoose · error · MongooseError

Attempting to remove virtual "${virtual}" that does not exis

Error message

Attempting to remove virtual "${virtual}" that does not exist.

What it means

removeVirtual only deletes names present in schema.virtuals, which stores exact dotted names as they were defined. Passing a name that was never registered (or is already removed, or sits at a different nesting depth) throws instead of silently succeeding, to surface cleanup mistakes.

Source

Thrown at lib/schema.js:2831

  delete branch[last];
}

/**
 * Removes the given virtual or virtuals from the schema.
 *
 * @param {string|Array} path The virutal path(s) to remove.
 * @returns {Schema} the Schema instance, or a mongoose error if the virtual does not exist.
 * @api public
 */

Schema.prototype.removeVirtual = function(path) {
  if (typeof path === 'string') {
    path = [path];
  }
  if (Array.isArray(path)) {
    for (const virtual of path) {
      if (this.virtuals[virtual] == null) {
        throw new MongooseError(`Attempting to remove virtual "${virtual}" that does not exist.`);
      }
    }

    for (const virtual of path) {
      delete this.paths[virtual];
      delete this.virtuals[virtual];
      if (virtual.indexOf('.') !== -1) {
        mpath.unset(virtual, this.tree);
      } else {
        delete this.tree[virtual];
      }
    }
  }
  return this;
};

/**
 * Loads an ES6 class into a schema. Maps [setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) + [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get), [static methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static),

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Inspect registered names first: `console.log(Object.keys(schema.virtuals))` and use the exact key.
  2. Guard removals: `if (schema.virtuals[name] != null) schema.removeVirtual(name)`.
  3. Build removal lists from Object.keys(schema.virtuals).filter(...) rather than duplicating names in config.

Example fix

// before
schema.removeVirtual('name.full'); // was actually defined as 'fullName'

// after
const target = Object.keys(schema.virtuals).find(n => n === 'fullName');
if (target) schema.removeVirtual(target);
Defensive patterns

Strategy: validation

Validate before calling

const removeVirtualIfExists = (schema, name) => {
  if (schema.virtuals[name] != null) schema.removeVirtual(name);
};
// or derive the list dynamically:
for (const name of Object.keys(schema.virtuals).filter(n => n.startsWith('tmp'))) {
  schema.removeVirtual(name);
}

Prevention

When it happens

Trigger: `schema.removeVirtual('name.full')` when the virtual was defined as 'fullName'; removing the same virtual twice; plugins removing virtuals that optional configuration never created.

Common situations: Conditional schemas (feature flags) where a virtual may or may not exist; refactors renaming virtuals without updating teardown code; loops calling removeVirtual over a stale hardcoded list.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/006e68f564067d98. Report an issue: GitHub.