transloadit/uppy · error · ValidationError

upload destination does not match any allowed destinations

Error message

upload destination does not match any allowed destinations

What it means

When the Companion server is configured with companionOptions.uploadUrls (an allowlist of permitted upload destinations), every supplied endpoint/uploadUrl must match at least one entry (via hasMatch). A well-formed but non-allowlisted URL triggers this ValidationError.

Source

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

  // 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')
  }
}

const states = {
  idle: 'idle',
  uploading: 'uploading',
  paused: 'paused',
  done: 'done',

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Add the client's exact destination URL to Companion's uploadUrls option (comma-separated via the UPLOAD_URLS env var)
  2. Check for trailing slashes, port numbers, or subdomain mismatches between the allowlist entry and the sent URL
  3. Redeploy/restart Companion after changing the allowlist so options are re-read

Example fix

# before
UPLOAD_URLS='["https://allowed.example.com/upload"]'

# after (client posts to https://uploads.allowed.example.com/upload)
UPLOAD_URLS='["https://allowed.example.com/upload", "https://uploads.allowed.example.com/upload"]'
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = ['https://allowed.example.com/upload'] // mirror server UPLOAD_URLS
const ok = (u: string) => ALLOWED.some((a) => u.startsWith(a))
if (!ok(endpoint)) throw new Error('endpoint not in server allowlist')

Try / catch

try { await uploader.upload() } catch (err) {
  if (err.message.includes('does not match any allowed destinations')) { /* update allowlist or endpoint */ }
}

Prevention

When it happens

Trigger: Companion started with UPLOAD_URLS='["https://allowed.example.com/upload"]' while the client sends endpoint 'https://other.example.com/upload'; or a glob pattern in uploadUrls that doesn't cover the subdomain/path used.

Common situations: Adding an upload allowlist for security and forgetting to include the client's actual destination; env var formatting mistakes (JSON string vs array); changing the client destination without updating the server allowlist.

Related errors


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