A failed drop must explain why
Aliases: silent drop rejection · drop failed · drag snap-back
What it is
The object followed the pointer a long way, then snapped back, or landed with no sequel. Failure needs a reason: type mismatch, read-only target, missing permission, target full, app busy, this region was never a drop zone. Across applications the source does not know why the target refused; if the target does not say, the whole channel looks broken.
The reason is the sentence after release, not the “cannot drop” cursor during the drag. The cursor prevents a mistaken release; the reason explains a refusal that already happened.
Why it happens
The two ends of a cross-app drag do not share internal state. The source sees that it handed data over; the target sees that it accepted or refused. The OS can express “no type match” as a cursor; it cannot speak for the target about “this item is locked,” “attachments over the limit,” “cannot write while syncing.” People parse a drag as one action. A failure with no sequel is blamed on the desktop channel itself: they stop dragging and export instead.
Snap-back is spatial “it did not go,” but it is ambiguous—wrong type, missing permission, release three pixels off the target all look the same. The reason has to land in the target window, as a sentence that can be acted on: another format, unlock first, a different folder. A toast in the source that “the other app refused” does not help, because the next step is on the target’s side. A short notice is enough; the drag already spent attention, and the failure must not open a modal that locks the person in.
Where it stops holding
Canceling mid-drag with Escape is not a failure and should not raise an error; the object returns quietly. A type mismatch already spoken as a “cannot drop” cursor during enter does not need another layer if release happens off a target. If release happens on a target that declared it would accept, and permission fails only at that instant, it must speak. A batch of twenty files with three wrong types should be summarized, not fired twenty times. A sandbox refusal is a system-level failure; the app still translates the system’s reason into a sentence a person can use, not an error code.
Applying it
- If a region looked droppable and still cannot write after release, put the reason and the next step (unlock, another format, smaller size) beside that region. Do not only snap the object back to the source.
- Separate cancel from failure: Escape or dragging back to the source is cancel; release on a target that then refuses is failure.
- Verify by dragging once onto a read-only target, once onto an unsupported type, once onto a target at capacity. Each time the reason must appear on the target’s side. Release on empty window chrome should cancel quietly, with no error. A multi-file drag should collapse failures into one summary.