{"record":{"id":"88e4880ed46b01dd","repo":"transloadit/uppy","slug":"companion-hostname-is-required-please-consult-htt-88e488","errorCode":null,"errorMessage":"Companion hostname is required, please consult https://uppy.io/docs/companion","messagePattern":"Companion hostname is required, please consult https://uppy\\.io/docs/companion","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/@uppy/url/src/Url.tsx","lineNumber":118,"sourceCode":"\n  canHandleRootDrop!: typeof canHandleRootDrop\n\n  constructor(uppy: Uppy<M, B>, opts: UrlOptions) {\n    super(uppy, opts)\n    this.id = this.opts.id || 'Url'\n    this.type = 'acquirer'\n    this.icon = () => <UrlIcon />\n\n    // Set default options and locale\n    this.defaultLocale = locale\n\n    this.i18nInit()\n    this.title = this.i18n('pluginNameUrl')\n\n    this.hostname = this.opts.companionUrl\n\n    if (!this.hostname) {\n      throw new Error(\n        'Companion hostname is required, please consult https://uppy.io/docs/companion',\n      )\n    }\n\n    this.client = new RequestClient(uppy, {\n      companionUrl: this.opts.companionUrl,\n      companionHeaders: this.opts.companionHeaders,\n      companionCookiesRule: this.opts.companionCookiesRule,\n    })\n\n    this.uppy.registerRequestClient(Url.requestClientId, this.client)\n  }\n\n  private getMeta = (url: string): Promise<MetaResponse> => {\n    return this.client.post<MetaResponse>('url/meta', { url })\n  }\n\n  private addFile = async (","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/transloadit/uppy/blob/5d4dedd02a1ac0ae022c75c54aca76558f88e256/packages/@uppy/url/src/Url.tsx#L100-L136","documentation":"The Url plugin (the 'Import from link' acquirer) fetches remote URLs through Companion, so a companionUrl is mandatory. The constructor throws when the resolved hostname is falsy before the internal RequestClient is created.","triggerScenarios":"new Url(uppy, { companionUrl: '' }) or omitting companionUrl entirely; also companionUrl set to undefined via conditional spread that evaluates falsy.","commonSituations":"Same-family config mistake as other provider plugins: examples omitting the option, wrong option name (companion vs companionUrl), empty environment variable in CI/staging, or assuming the plugin fetches URLs client-side without a server.","solutions":["Provide companionUrl pointing at your running Companion instance","Deploy Companion (yarn start:companion in dev) or use a hosted Companion endpoint","Double-check the exact option key is companionUrl and the value is non-empty at runtime"],"exampleFix":"// before\nuppy.use(Url, { companionUrl: process.env.COMPANION_URL })\n\n// after\nconst companionUrl = process.env.COMPANION_URL\nif (companionUrl) uppy.use(Url, { companionUrl })","handlingStrategy":"validation","validationCode":"const companionUrl = process.env.COMPANION_URL\nif (!companionUrl) throw new Error('COMPANION_URL must be set to use the Url plugin')\nuppy.use(Url, { companionUrl })","typeGuard":"const hasCompanionUrl = (opts: { companionUrl?: string }): opts is { companionUrl: string } => typeof opts.companionUrl === 'string' && opts.companionUrl.length > 0","tryCatchPattern":"try { uppy.use(Url, { companionUrl }) } catch (e) { if (e.message.includes('Companion hostname')) console.warn('Url plugin skipped') }","preventionTips":["Gate plugin registration on a validated companionUrl","Use the exact key name companionUrl","Test config in every environment (dev/staging/prod)"],"tags":["companion","configuration","url-plugin","required-option"],"backgroundTag":"missing-required-config","analyzedSha":"5d4dedd02a1ac0ae022c75c54aca76558f88e256","analyzedAt":"2026-08-28T12:18:41.267Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}