multica-ai/multica · error · Error
Invalid desktop runtime config: ${field} must use ws or wss
Error message
Invalid desktop runtime config: ${field} must use ws or wss What it means
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.
Source
Thrown at apps/desktop/src/shared/runtime-config.ts:165
throw new Error(`Invalid desktop runtime config: ${field} must be a valid URL`);
}
if (url.protocol !== "http:" && url.protocol !== "https:") {
throw new Error(`Invalid desktop runtime config: ${field} must use http or https`);
}
url.search = "";
url.hash = "";
return trimTrailingSlash(url.toString());
}
function normalizeWsUrl(value: string, field: string): string {
let url: URL;
try {
url = new URL(value.trim());
} catch {
throw new Error(`Invalid desktop runtime config: ${field} must be a valid URL`);
}
if (url.protocol !== "ws:" && url.protocol !== "wss:") {
throw new Error(`Invalid desktop runtime config: ${field} must use ws or wss`);
}
url.search = "";
url.hash = "";
return trimTrailingSlash(url.toString());
}
function joinPath(base: string, suffix: string): string {
const normalizedBase = base.endsWith("/") ? base.slice(0, -1) : base;
return `${normalizedBase}${suffix}`;
}
function trimTrailingSlash(value: string): string {
return value.replace(/\/+$/, "");
}
View on GitHub (pinned to 2c0912b6ec)
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.
Example fix
// before name := "profiles" // reserved home, mustExist, err := hermesProfileDir(root, name) // err: reserved // after name := "team-profiles" home, mustExist, err := hermesProfileDir(root, name)
Defensive patterns
Strategy: validation
Validate before calling
var hermesReservedProfileNames = map[string]bool{"profiles": true /* keep in sync with hermes_home.go */}
func usableHermesProfileName(name string) bool {
n := strings.ToLower(strings.TrimSpace(name))
return n != "" && n != "default" && !hermesReservedProfileNames[n]
} Type guard
func isReservedHermesProfile(name string) bool {
_, reserved := hermesReservedProfileNames[strings.ToLower(strings.TrimSpace(name))]
return reserved
} Try / catch
home, mustExist, err := hermesProfileDir(root, name)
if err != nil && strings.Contains(err.Error(), "is reserved") {
// prompt for a rename; block reserved words at the entry point
} Prevention
- 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.
When it happens
Trigger: 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").
Common situations: 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.
Related errors
- Invalid desktop runtime config: ${field} must use http or ht
- mint PAT: target API URL not set
- mint PAT: response missing token
- daemon profile is not resolved yet; token sync skipped
- API error: ${res.status} ${res.statusText}
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/5fedd1551e03a03b.
Report an issue: GitHub.