dianping/cat · error · Error

Dropzone already attached.

Error message

Dropzone already attached.

What it means

Dropzone stamps the DOM element with element.dropzone = this as a marker. If the constructor runs on an element that already has that property (a Dropzone instance already constructed on it), it throws to prevent double registration of listeners, which would duplicate uploads and previews.

Source

Thrown at cat-home/src/main/webapp/assets/js/uncompressed/dropzone.js:582

      return target;
    };

    function Dropzone(element, options) {
      var elementOptions, fallback, _ref;
      this.element = element;
      this.version = Dropzone.version;
      this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\n*/g, "");
      this.clickableElements = [];
      this.listeners = [];
      this.files = [];
      if (typeof this.element === "string") {
        this.element = document.querySelector(this.element);
      }
      if (!(this.element && (this.element.nodeType != null))) {
        throw new Error("Invalid dropzone element.");
      }
      if (this.element.dropzone) {
        throw new Error("Dropzone already attached.");
      }
      Dropzone.instances.push(this);
      this.element.dropzone = this;
      elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {};
      this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {});
      if (this.options.forceFallback || !Dropzone.isBrowserSupported()) {
        return this.options.fallback.call(this);
      }
      if (this.options.url == null) {
        this.options.url = this.element.getAttribute("action");
      }
      if (!this.options.url) {
        throw new Error("No URL provided.");
      }
      if (this.options.acceptedFiles && this.options.acceptedMimeTypes) {
        throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
      }
      if (this.options.acceptedMimeTypes) {

View on GitHub (pinned to e815e74d4c)

Solutions

  1. If you initialize manually with new Dropzone(el), disable autodiscover first: Dropzone.autoDiscover = false; (before DOMContentLoaded).
  2. Guard re-initialization: if (el.dropzone) return el.dropzone;
  3. For re-rendered content, destroy the old instance (instance.destroy()) before creating a new one.

Example fix

// before
Dropzone.autoDiscover defaults to true;
new Dropzone('#up'); // second init on same element -> throws

// after
Dropzone.options.autoDiscover = false;
Dropzone.autoDiscover = false;
new Dropzone('#up', { url: '/upload' });
Defensive patterns

Strategy: validation

Validate before calling

Dropzone.autoDiscover = false; // once, before any init if you construct manually
var el = document.querySelector('#up');
if (el && !el.dropzone) {
  new Dropzone(el, { url: '/upload' });
}

Type guard

function isDropzoneAttached(el) {
  return !!(el && el.dropzone instanceof Dropzone);
}

Prevention

When it happens

Trigger: Calling new Dropzone(el) twice on the same element; manually calling new Dropzone('.dropzone') on elements that Dropzone.autoDiscover already initialized on DOMContentLoaded; re-running page initialization code (e.g. after an AJAX partial re-render) without checking.

Common situations: Including dropzone.js (autoDiscover defaults to true) AND manually constructing a Dropzone on the same .dropzone element — the classic double-init; re-attaching after Turbegrids/partial page updates; duplicated ready handlers.

Related errors


AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14). Data as JSON: /api/errors/f96abd7e50aedd59. Report an issue: GitHub.