{"record":{"id":"ed8b87c9415736c8","repo":"langgenius/dify","slug":"usageinvalidflag-ed8b87","errorCode":"UsageInvalidFlag","errorMessage":"host parse: ${(err as Error).message}","messagePattern":"host parse: (.+?)","errorType":"error_code","errorClass":"BaseError","httpStatus":null,"severity":"error","filePath":"cli/src/util/host.ts","lineNumber":24,"sourceCode":"\nexport function openAPIBase(host: string): string {\n  return `${host.replace(/\\/+$/, '')}/openapi/v1/`\n}\n\nexport type ResolveHostOptions = {\n  raw: string\n  insecure: boolean\n}\n\nexport function resolveHost(opts: ResolveHostOptions): string {\n  let raw = opts.raw.trim()\n  if (raw === '') raw = DEFAULT_HOST\n  if (!raw.includes('://')) raw = `https://${raw}`\n  let url: URL\n  try {\n    url = new URL(raw)\n  } catch (err) {\n    throw new BaseError({\n      code: ErrorCode.UsageInvalidFlag,\n      message: `host parse: ${(err as Error).message}`,\n    })\n  }\n  url.pathname = url.pathname.replace(/\\/+$/, '')\n  if (url.protocol !== 'https:' && !(opts.insecure && url.protocol === 'http:')) {\n    throw new BaseError({\n      code: ErrorCode.UsageInvalidFlag,\n      message: 'only https:// hosts are accepted',\n      hint: 'add --insecure to allow http:// (local-dev only; user_code/device_code travel plaintext)',\n    })\n  }\n  const out = url.toString()\n  return out.endsWith('/') ? out.slice(0, -1) : out\n}\n\nexport function hostWithScheme(host: string, scheme: string | undefined): string {\n  if (host.includes('://')) return host","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/cli/src/util/host.ts#L6-L42","documentation":"BaseError(UsageInvalidFlag, exit 2) from resolveHost (host.ts:24) when `new URL(raw)` throws. Before reaching URL, resolveHost trims, defaults empty to DEFAULT_HOST (https://cloud.dify.ai), and prepends 'https://' if no '://' is present — so the parse only fails on values that remain malformed even after those fixes: embedded spaces, control chars, invalid percent-encoding, or a scheme that URL rejects. The original parser message is appended (e.g. 'Invalid URL').","triggerScenarios":"`--host 'cloud dify ai'` (spaces), `--host 'https://cloud.dify.ai/space path'` (space in path before scheme-stripping — though URL may tolerate some of these), `--host '%zz'` (bad percent-encoding), or a value with control characters. Most plain hostname typos get rescued by the `https://` prepend and parse fine, then possibly fail DNS later.","commonSituations":"Copy-pasting a host with a trailing path that includes characters URL rejects; shell quoting that let a space in; env var with stray characters; a host string that includes credentials with special chars ('@', ':') confusing the URL parser into a malformed authority.","solutions":["Pass a clean host: `--host cloud.dify.ai` or `--host https://cloud.dify.ai` (no path, no spaces).","Shell-quote values containing special characters, and prefer to avoid embedded spaces in hostnames entirely.","Strip trailing slashes and paths — resolveHost normalizes the pathname but the host itself should be just scheme://host[:port].","If your host genuinely needs an unusual character, percent-encode it per RFC 3986."],"exampleFix":"# before\nexport DIFY_HOST='cloud dify ai'\ndifyctl --host \"$DIFY_HOST\" apps list   # URL parse fails on the space\n\n# after\nexport DIFY_HOST='cloud.dify.ai'\ndifyctl --host \"$DIFY_HOST\" apps list","handlingStrategy":"validation","validationCode":"// validate the host string the same way resolveHost does, before calling the command\nfunction preValidateHost(raw: string): URL {\n  let s = raw.trim()\n  if (s === '') s = 'https://cloud.dify.ai'\n  if (!s.includes('://')) s = `https://${s}`\n  try {\n    return new URL(s)\n  } catch (err) {\n    throw new Error(`host parse: ${(err as Error).message}`)\n  }\n}","typeGuard":"function isParsableHost(raw: string): boolean {\n  try {\n    let s = raw.trim()\n    if (s === '') return true\n    if (!s.includes('://')) s = `https://${s}`\n    new URL(s)\n    return true\n  } catch {\n    return false\n  }\n}","tryCatchPattern":null,"preventionTips":["Pass bare hostnames (`cloud.dify.ai`) and let difyctl add the scheme.","Strip spaces and stray paths before passing.","Validate with `new URL(...)` in your wrapper if the value comes from user input or env."],"tags":["cli","host","url","parsing","usage"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}