transloadit/uppy · error · Error

isDropOrPaste must be either 'drop' or 'paste', but it's

Error message

isDropOrPaste must be either 'drop' or 'paste', but it's ${isDropOrPaste}

What it means

forEachDroppedOrPastedUrl's switch on isDropOrPaste hit its default case, meaning the caller passed something other than the literal strings 'drop' or 'paste'. It is a programming-error guard for the internal API's discriminant parameter.

Solutions

  1. Pass exactly 'drop' from drop handlers and 'paste' from paste handlers
  2. If you don't control the string, narrow it before calling: only invoke when value === 'drop' || value === 'paste'

Example fix

// before
forEachDroppedOrPastedUrl(event, cb, 'dragover')
// after
forEachDroppedOrPastedUrl(event, cb, 'drop')
Defensive patterns

Strategy: type-guard

Validate before calling

if (kind !== 'drop' && kind !== 'paste') return

Type guard

const isDropOrPaste = (v: string): v is 'drop' | 'paste' => v === 'drop' || v === 'paste'

Prevention

When it happens

Trigger: Calling forEachDroppedOrPastedUrl(event, cb, 'dragover' | 'input' | undefined | anyOtherValue) instead of 'drop' or 'paste'.

Common situations: Custom integrations or forks invoking the util directly with a wrong event-type string; typos like 'drops' or 'Drop'.

Understand the failure class

Background: "invalid argument", "unknown mode", "not supported": invalid enum-like argument errors explained — this error's family across 19 libraries.

Related errors


AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28). Data as JSON: /api/errors/fe552d401b50bca2. Report an issue: GitHub.

Appendix: source

Thrown at packages/@uppy/url/src/utils/forEachDroppedOrPastedUrl.ts:85

    case 'paste': {
      const atLeastOneFileIsDragged = items.some((item) => item.kind === 'file')
      if (atLeastOneFileIsDragged) {
        return
      }
      urlItems = items.filter(
        (item) => item.kind === 'string' && item.type === 'text/plain',
      )

      break
    }
    case 'drop': {
      urlItems = items.filter(
        (item) => item.kind === 'string' && item.type === 'text/uri-list',
      )
      break
    }
    default: {
      throw new Error(
        `isDropOrPaste must be either 'drop' or 'paste', but it's ${isDropOrPaste}`,
      )
    }
  }

  urlItems.forEach((item) => {
    item.getAsString((urlString) => callback(urlString))
  })
}

View on GitHub (pinned to 5d4dedd02a)