{"record":{"id":"5fedd1551e03a03b","repo":"multica-ai/multica","slug":"invalid-desktop-runtime-config-field-must-use-5fedd1","errorCode":null,"errorMessage":"Invalid desktop runtime config: ${field} must use ws or wss","messagePattern":"Invalid desktop runtime config: (.+?) must use ws or wss","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/src/shared/runtime-config.ts","lineNumber":165,"sourceCode":"    throw new Error(`Invalid desktop runtime config: ${field} must be a valid URL`);\n  }\n  if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n    throw new Error(`Invalid desktop runtime config: ${field} must use http or https`);\n  }\n  url.search = \"\";\n  url.hash = \"\";\n  return trimTrailingSlash(url.toString());\n}\n\nfunction normalizeWsUrl(value: string, field: string): string {\n  let url: URL;\n  try {\n    url = new URL(value.trim());\n  } catch {\n    throw new Error(`Invalid desktop runtime config: ${field} must be a valid URL`);\n  }\n  if (url.protocol !== \"ws:\" && url.protocol !== \"wss:\") {\n    throw new Error(`Invalid desktop runtime config: ${field} must use ws or wss`);\n  }\n  url.search = \"\";\n  url.hash = \"\";\n  return trimTrailingSlash(url.toString());\n}\n\nfunction joinPath(base: string, suffix: string): string {\n  const normalizedBase = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n  return `${normalizedBase}${suffix}`;\n}\n\nfunction trimTrailingSlash(value: string): string {\n  return value.replace(/\\/+$/, \"\");\n}\n","sourceCodeStart":147,"sourceCodeEnd":180,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/apps/desktop/src/shared/runtime-config.ts#L147-L180","documentation":"Validation error from hermesProfileDir: the canonicalized name is in hermesReservedProfileNames, so it cannot be used as a profile. Reserved names would collide with structural directories/files inside HERMES_HOME (the map is defined alongside the regex in hermes_home.go), hence they are rejected exactly like the Hermes CLI does.","triggerScenarios":"hermesProfileDir is called with a name that canonicalizes to one of the entries in hermesReservedProfileNames — the reserved set excludes names the overlay itself uses (anything colliding with root-level layout such as \"profiles\").","commonSituations":"A user names a profile \"profiles\" or another structural entry without realizing the CLI reserves it; after a hermes version upgrade adds new reserved names, previously valid configs start failing; shared default configs that used an now-reserved word.","solutions":["Pick a different, non-reserved profile name (check hermesReservedProfileNames in server/internal/daemon/execenv/hermes_home.go for the exact set).","After upgrading the hermes CLI/daemon, review release notes for newly reserved names and rename affected profiles.","Enforce the reserved list at agent-config validation time, not at task prepare time."],"exampleFix":"// before\nname := \"profiles\" // reserved\nhome, mustExist, err := hermesProfileDir(root, name) // err: reserved\n\n// after\nname := \"team-profiles\"\nhome, mustExist, err := hermesProfileDir(root, name)","handlingStrategy":"validation","validationCode":"var hermesReservedProfileNames = map[string]bool{\"profiles\": true /* keep in sync with hermes_home.go */}\nfunc usableHermesProfileName(name string) bool {\n    n := strings.ToLower(strings.TrimSpace(name))\n    return n != \"\" && n != \"default\" && !hermesReservedProfileNames[n]\n}","typeGuard":"func isReservedHermesProfile(name string) bool {\n    _, reserved := hermesReservedProfileNames[strings.ToLower(strings.TrimSpace(name))]\n    return reserved\n}","tryCatchPattern":"home, mustExist, err := hermesProfileDir(root, name)\nif err != nil && strings.Contains(err.Error(), \"is reserved\") {\n    // prompt for a rename; block reserved words at the entry point\n}","preventionTips":["Maintain the reserved-name list in your validation layer and sync it on daemon upgrades.","Prefix auto-generated profile names (e.g. \"agent-\") to dodge structural collisions.","Check release notes when upgrading hermes for new reserved names."],"tags":["go","hermes","validation","profile","reserved-names","execenv"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}