{"record":{"id":"e3b458de23376fb8","repo":"transloadit/uppy","slug":"unsupported-protocol-specified","errorCode":null,"errorMessage":"unsupported protocol specified","messagePattern":"unsupported protocol specified","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"packages/@uppy/companion/src/server/Uploader.ts","lineNumber":145,"sourceCode":"    throw new ValidationError('fieldname must be a string')\n  }\n\n  // validate metadata (optional)\n  if (options.metadata != null && typeof options.metadata !== 'object') {\n    throw new ValidationError('metadata must be an object')\n  }\n\n  // validate headers (optional)\n  if (options.headers != null && typeof options.headers !== 'object') {\n    throw new ValidationError('headers must be an object')\n  }\n\n  // validate protocol (optional)\n  if (\n    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","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/companion/src/server/Uploader.ts#L127-L163","documentation":"The optional protocol option must be one of the PROTOCOLS enum values (e.g. 'tus', 's3-multipart', 'xhr-upload' style identifiers). Any other non-falsy value throws a ValidationError.","triggerScenarios":"new Uploader({ protocol: 'ftp' }) or a typo like 's3multipart' (missing the exact enum value) — anything not in Object.values(PROTOCOLS).","commonSituations":"Custom integrations guessing protocol strings instead of importing PROTOCOLS; version changes renaming enum values; case mismatches.","solutions":["Import PROTOCOLS from the Uploader module and use PROTOCOLS.s3Multipart etc.","Match the exact enum string (e.g. 's3-multipart' with correct spelling/hyphenation)","Omit protocol when the default applies"],"exampleFix":"// before\nnew Uploader({ protocol: 's3multipart', ... })\n\n// after\nimport { PROTOCOLS } from '../server/Uploader.js'\nnew Uploader({ protocol: PROTOCOLS.s3Multipart, ... })","handlingStrategy":"validation","validationCode":"import { PROTOCOLS } from '@uppy/companion/src/server/Uploader.js'\nif (protocol && !Object.values(PROTOCOLS).includes(protocol)) throw new Error('bad protocol')","typeGuard":"const isProtocol = (p: unknown, PROTOCOLS: Record<string, string>) => typeof p === 'string' && Object.values(PROTOCOLS).includes(p)","tryCatchPattern":"null","preventionTips":["Import the PROTOCOLS enum instead of hardcoding strings","Re-check enum values on Companion upgrades"],"tags":["companion","uploader","validation","protocol","enum"],"backgroundTag":"invalid-enum-value","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}