{"record":{"id":"7d2bdb4f127d11f3","repo":"transloadit/uppy","slug":"invalid-destination-url","errorCode":null,"errorMessage":"invalid destination url","messagePattern":"invalid destination url","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"packages/@uppy/companion/src/server/Uploader.ts","lineNumber":160,"sourceCode":"    options.protocol &&\n    !Object.values(PROTOCOLS).includes(options.protocol)\n  ) {\n    throw new ValidationError('unsupported protocol specified')\n  }\n\n  // s3 uploads don't require upload destination\n  // validation, because the destination is determined\n  // by the server's s3 config\n  if (options.protocol !== PROTOCOLS.s3Multipart) {\n    if (!options.endpoint && !options.uploadUrl) {\n      throw new ValidationError('no destination specified')\n    }\n\n    const validateUrl = (url: string | undefined): void => {\n      if (url == null) return\n      const validatorOpts = { require_protocol: true, require_tld: false }\n      if (!validator.isURL(url, validatorOpts)) {\n        throw new ValidationError('invalid destination url')\n      }\n\n      const allowedUrls = options.companionOptions.uploadUrls\n      if (allowedUrls && !hasMatch(url, allowedUrls)) {\n        throw new ValidationError(\n          'upload destination does not match any allowed destinations',\n        )\n      }\n    }\n\n    ;[options.endpoint, options.uploadUrl].forEach(validateUrl)\n  }\n\n  if (options.chunkSize != null && typeof options.chunkSize !== 'number') {\n    throw new ValidationError('incorrect chunkSize')\n  }\n}\n","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/companion/src/server/Uploader.ts#L142-L178","documentation":"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.","triggerScenarios":"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.","commonSituations":"Building the endpoint from a config/env var that lacks the scheme, using a relative URL, or a malformed URL after string concatenation.","solutions":["Prefix the URL with a protocol, e.g. 'http://example.com/upload' or 'https://...'","Log/inspect the exact endpoint and uploadUrl strings sent to Companion and fix malformed values","If using localhost, note require_tld:false permits it but the protocol is still mandatory"],"exampleFix":"// before\nendpoint: 'localhost:3000/upload'\n\n// after\nendpoint: 'http://localhost:3000/upload'","handlingStrategy":"validation","validationCode":"import validator from 'validator'\nconst valid = (u?: string) => u == null || validator.isURL(u, { require_protocol: true, require_tld: false })\nif (!valid(opts.endpoint) || !valid(opts.uploadUrl)) throw new Error('bad destination url')","typeGuard":"const isUrlWithProtocol = (u: unknown): u is string =>\n  typeof u === 'string' && /^https?:\\/\\/.+/.test(u);","tryCatchPattern":"try { await uploader.upload() } catch (err) {\n  if (err instanceof ValidationError && err.message === 'invalid destination url') { /* fix URL scheme */ }\n}","preventionTips":["Centralize URL construction and always prepend http(s)://","Assert URLs client-side with the same validator settings before sending"],"tags":["companion","uploader","url-validation"],"backgroundTag":"invalid-url-format","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}