{"record":{"id":"927c02bd78a98fe2","repo":"NousResearch/hermes-agent","slug":"invalid-profile-name-value","errorCode":null,"errorMessage":"Invalid profile name: ${value}","messagePattern":"Invalid profile name: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/main.ts","lineNumber":6915,"sourceCode":"    const raw = fs.readFileSync(DESKTOP_PROFILE_CONFIG_PATH, 'utf8')\n    const parsed = JSON.parse(raw)\n    const name = parsed && typeof parsed.profile === 'string' ? parsed.profile.trim() : ''\n\n    if (name && (name === 'default' || PROFILE_NAME_RE.test(name))) {\n      return name\n    }\n  } catch {\n    // Missing or malformed → no preference.\n  }\n\n  return null\n}\n\nfunction writeActiveDesktopProfile(name) {\n  const value = typeof name === 'string' ? name.trim() : ''\n\n  if (value && value !== 'default' && !PROFILE_NAME_RE.test(value)) {\n    throw new Error(`Invalid profile name: ${value}`)\n  }\n\n  fs.mkdirSync(path.dirname(DESKTOP_PROFILE_CONFIG_PATH), { recursive: true })\n  writeFileAtomic(DESKTOP_PROFILE_CONFIG_PATH, JSON.stringify({ profile: value || null }, null, 2))\n\n  return value || null\n}\n\n// Sanitize a connection config into the renderer-facing shape. With no\n// `profile` this describes the global/default connection (the existing\n// behavior); with a `profile` it describes that profile's per-profile remote\n// override (or an empty \"local/inherit\" view when the profile has none).\nasync function sanitizeDesktopConnectionConfig(config = readDesktopConnectionConfig(), profile = null) {\n  const key = connectionScopeKey(profile)\n  const scoped = key ? config.profiles?.[key] || null : null\n  const block = key ? scoped || {} : config.remote || {}\n\n  const envOverride = key ? false : Boolean(process.env.HERMES_DESKTOP_REMOTE_URL)","sourceCodeStart":6897,"sourceCodeEnd":6933,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/electron/main.ts#L6897-L6933","documentation":"Thrown by writeActiveDesktopProfile when the profile name being persisted is non-empty, not the literal 'default', and fails PROFILE_NAME_RE — the validation regex governing profile names. The value is trimmed first, so the check runs on the effective string that would be written to DESKTOP_PROFILE_CONFIG_PATH.","triggerScenarios":"Setting the active desktop profile to a name containing characters outside PROFILE_NAME_RE (spaces, dots, slashes, unicode, etc. depending on the regex); passing 'default' is allowed only as the literal — any other reserved-looking name must match the regex.","commonSituations":"Programmatically writing a profile name sourced from user input or another config without sanitizing; renaming a profile to include characters the desktop forbids.","solutions":["Use a profile name matching PROFILE_NAME_RE (typically lowercase alphanumerics, '-', '_').","Trim whitespace before passing the name — the code trims for the test, but keep inputs clean at the source.","Reserve 'default' for the default profile; pick a distinct name otherwise."],"exampleFix":"// before\nwriteActiveDesktopProfile('my profile!')\n\n// after\nconst PROFILE_NAME_SAFE = /^[a-z0-9][a-z0-9_-]*$/i\nconst name = 'my profile!'\nif (!PROFILE_NAME_SAFE.test(name)) throw new Error(`Invalid profile name: ${name}`)\nwriteActiveDesktopProfile(name)","handlingStrategy":"validation","validationCode":"const PROFILE_NAME_SAFE = /^[A-Za-z0-9][A-Za-z0-9_-]*$/ // mirror PROFILE_NAME_RE\nfunction isValidProfileName(name) {\n  const v = typeof name === 'string' ? name.trim() : ''\n  return v === '' || v === 'default' || PROFILE_NAME_SAFE.test(v)\n}","typeGuard":"function isWritableProfileName(name) {\n  const v = String(name || '').trim()\n  return v === '' || v === 'default' || PROFILE_NAME_SAFE.test(v)\n}","tryCatchPattern":null,"preventionTips":["Restrict profile names to the safe alphabet at the input field","Trim before persisting","Treat 'default' as reserved"],"tags":["profiles","validation","config","desktop"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}