{"record":{"id":"f44dee388c171590","repo":"Shopify/draggable","slug":"not-implemented","errorCode":null,"errorMessage":"Not Implemented","messagePattern":"Not Implemented","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/shared/AbstractPlugin/AbstractPlugin.ts","lineNumber":22,"sourceCode":" * All draggable plugins inherit from this class.\n * @abstract\n * @class AbstractPlugin\n * @module AbstractPlugin\n */\nexport abstract class AbstractPlugin {\n  /**\n   * AbstractPlugin constructor.\n   * @constructs AbstractPlugin\n   * @param {Draggable} draggable - Draggable instance\n   */\n  constructor(protected draggable: FixMeAny) {}\n\n  /**\n   * Override to add listeners\n   * @abstract\n   */\n  attach() {\n    throw new Error('Not Implemented');\n  }\n\n  /**\n   * Override to remove listeners\n   * @abstract\n   */\n  detach() {\n    throw new Error('Not Implemented');\n  }\n}\n","sourceCodeStart":4,"sourceCodeEnd":33,"githubUrl":"https://github.com/Shopify/draggable/blob/8a1eed57f3ab2dff9371e8ce60fb39ac85871e8d/src/shared/AbstractPlugin/AbstractPlugin.ts#L4-L33","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nclass MyPlugin extends AbstractPlugin {}\nconst plugin = new MyPlugin(draggable);\nplugin.attach(); // throws Not Implemented\n\n// after\nclass MyPlugin extends AbstractPlugin {\n  attach() {\n    this.draggable.on('drag:start', this.onDragStart);\n  }\n}\nconst plugin = new MyPlugin(draggable);\nplugin.attach();","handlingStrategy":"type-guard","validationCode":"function isConcretePlugin(PluginClass) {\n  return typeof PluginClass === 'function' &&\n    PluginClass.prototype.attach !== AbstractPlugin.prototype.attach &&\n    PluginClass !== AbstractPlugin;\n}\n// guard before use: if (!isConcretePlugin(MyPlugin)) throw ...","typeGuard":"function implementsAttach(instance) {\n  return instance instanceof AbstractPlugin &&\n    instance.attach !== AbstractPlugin.prototype.attach;\n}","tryCatchPattern":"try {\n  plugin.attach();\n} catch (e) {\n  if (e.message === 'Not Implemented') {\n    console.error(`${plugin.constructor.name} forgot to override attach()`);\n  } else {\n    throw e;\n  }\n}","preventionTips":["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()"],"tags":["javascript","typescript","abstract-method","subclassing","not-implemented"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"8a1eed57f3ab2dff9371e8ce60fb39ac85871e8d","analyzedAt":"2026-09-02T20:51:07.383Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}