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
- In your subclass, define `attach() { /* add your event listeners here */ }` overriding the base method
- 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
- If you only need a no-op plugin, explicitly define `attach() {}` rather than instantiating AbstractPlugin directly
- 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
- Always override attach() when subclassing AbstractPlugin
- Never instantiate AbstractPlugin directly; only concrete subclasses
- Check for method-name typos that silently fall back to the base implementation
- Add a unit test that instantiates every custom plugin and calls attach()
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.