transloadit/uppy · error · ValidationError

invalid destination url

Error message

invalid destination url

What it means

Companion validates the provided upload destination URL with the `validator` library using { require_protocol: true, require_tld: false }. If `endpoint` or `uploadUrl` fails this check (e.g. missing protocol scheme), ValidationError 'invalid destination url' is thrown from validateOptions.

Source

Thrown at packages/@uppy/companion/src/server/Uploader.ts:160

    options.protocol &&
    !Object.values(PROTOCOLS).includes(options.protocol)
  ) {
    throw new ValidationError('unsupported protocol specified')
  }

  // s3 uploads don't require upload destination
  // validation, because the destination is determined
  // by the server's s3 config
  if (options.protocol !== PROTOCOLS.s3Multipart) {
    if (!options.endpoint && !options.uploadUrl) {
      throw new ValidationError('no destination specified')
    }

    const validateUrl = (url: string | undefined): void => {
      if (url == null) return
      const validatorOpts = { require_protocol: true, require_tld: false }
      if (!validator.isURL(url, validatorOpts)) {
        throw new ValidationError('invalid destination url')
      }

      const allowedUrls = options.companionOptions.uploadUrls
      if (allowedUrls && !hasMatch(url, allowedUrls)) {
        throw new ValidationError(
          'upload destination does not match any allowed destinations',
        )
      }
    }

    ;[options.endpoint, options.uploadUrl].forEach(validateUrl)
  }

  if (options.chunkSize != null && typeof options.chunkSize !== 'number') {
    throw new ValidationError('incorrect chunkSize')
  }
}

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Prefix the URL with a protocol, e.g. 'http://example.com/upload' or 'https://...'
  2. Log/inspect the exact endpoint and uploadUrl strings sent to Companion and fix malformed values
  3. If using localhost, note require_tld:false permits it but the protocol is still mandatory

Example fix

// before
endpoint: 'localhost:3000/upload'

// after
endpoint: 'http://localhost:3000/upload'
Defensive patterns

Strategy: validation

Validate before calling

import validator from 'validator'
const valid = (u?: string) => u == null || validator.isURL(u, { require_protocol: true, require_tld: false })
if (!valid(opts.endpoint) || !valid(opts.uploadUrl)) throw new Error('bad destination url')

Type guard

const isUrlWithProtocol = (u: unknown): u is string =>
  typeof u === 'string' && /^https?:\/\/.+/.test(u);

Try / catch

try { await uploader.upload() } catch (err) {
  if (err instanceof ValidationError && err.message === 'invalid destination url') { /* fix URL scheme */ }
}

Prevention

When it happens

Trigger: Passing endpoint: 'example.com/upload' (no http://), 'ftp://example.com', 'http://' with nothing else, or any string that validator.isURL rejects under require_protocol: true, require_tld: false.

Common situations: Building the endpoint from a config/env var that lacks the scheme, using a relative URL, or a malformed URL after string concatenation.

Related errors


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