Shopify/draggable · error

Not Implemented

Error message

Not Implemented

What it means

AbstractPlugin is a base class whose `attach()` method is intentionally abstract: it only exists so subclasses override it with real event-listener wiring. The base implementation throws 'Not Implemented' to catch misuse — instantiating AbstractPlugin directly, or a subclass that forgot to override attach(). It is thrown at runtime when `attach()` is called on such an instance.

Source

Thrown at src/shared/AbstractPlugin/AbstractPlugin.ts:22

 * All draggable plugins inherit from this class.
 * @abstract
 * @class AbstractPlugin
 * @module AbstractPlugin
 */
export abstract class AbstractPlugin {
  /**
   * AbstractPlugin constructor.
   * @constructs AbstractPlugin
   * @param {Draggable} draggable - Draggable instance
   */
  constructor(protected draggable: FixMeAny) {}

  /**
   * Override to add listeners
   * @abstract
   */
  attach() {
    throw new Error('Not Implemented');
  }

  /**
   * Override to remove listeners
   * @abstract
   */
  detach() {
    throw new Error('Not Implemented');
  }
}

View on GitHub (pinned to 8a1eed57f3)

Solutions

  1. In your subclass, define `attach() { /* add your event listeners here */ }` overriding the base method
  2. Verify the subclass is actually the one being instantiated — check for typos in the method name so you are not silently falling back to the base implementation
  3. If you only need a no-op plugin, explicitly define `attach() {}` rather than instantiating AbstractPlugin directly
  4. Never call `attach()` on AbstractPlugin itself; only on concrete subclass instances

Example fix

// before
class MyPlugin extends AbstractPlugin {}
const plugin = new MyPlugin(draggable);
plugin.attach(); // throws Not Implemented

// after
class MyPlugin extends AbstractPlugin {
  attach() {
    this.draggable.on('drag:start', this.onDragStart);
  }
}
const plugin = new MyPlugin(draggable);
plugin.attach();
Defensive patterns

Strategy: type-guard

Validate before calling

function isConcretePlugin(PluginClass) {
  return typeof PluginClass === 'function' &&
    PluginClass.prototype.attach !== AbstractPlugin.prototype.attach &&
    PluginClass !== AbstractPlugin;
}
// guard before use: if (!isConcretePlugin(MyPlugin)) throw ...

Type guard

function implementsAttach(instance) {
  return instance instanceof AbstractPlugin &&
    instance.attach !== AbstractPlugin.prototype.attach;
}

Try / catch

try {
  plugin.attach();
} catch (e) {
  if (e.message === 'Not Implemented') {
    console.error(`${plugin.constructor.name} forgot to override attach()`);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling `attach()` directly on an `AbstractPlugin` instance; creating `class MyPlugin extends AbstractPlugin {}` (or a subclass that does not define `attach`) and registering it with Draggable, which calls `plugin.attach()` during initialization.

Common situations: Renaming `attach` to `attached` or a typo like `atatch` in a subclass so the base method remains; instantiating the abstract base as a placeholder during prototyping; a version change where the library renamed the expected method and old custom plugins no longer override it.

Understand the failure class

Background: "NotImplementedError: Subclasses should override this method" / "must be implemented" — abstract method errors explained — this error's family across 40 libraries.

Related errors


AI-assisted analysis of Shopify/draggable@8a1eed57f3 (2026-09-02). Data as JSON: /api/errors/f44dee388c171590. Report an issue: GitHub.