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
- Add the client's exact destination URL to Companion's uploadUrls option (comma-separated via the UPLOAD_URLS env var)
- Check for trailing slashes, port numbers, or subdomain mismatches between the allowlist entry and the sent URL
- 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
- Keep the client endpoint and server UPLOAD_URLS list in one config source
- Add integration tests that assert the configured endpoint passes the allowlist
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
- uploadUrls is required
- Option corsOrigins cannot be "*". To disable security, pass
- unsupported HTTP METHOD specified
- maxFileSize exceeded
- fieldname must be a string
AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28).
Data as JSON: /api/errors/b475b6b8b5331f21.
Report an issue: GitHub.