{"record":{"id":"2913b10e650d43a5","repo":"NousResearch/hermes-agent","slug":"remote-path-must-be-absolute-or-start-with","errorCode":null,"errorMessage":"Remote path must be absolute or start with ~/: \"${s}\"","messagePattern":"Remote path must be absolute or start with ~/: \"(.+?)\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/remote-lifecycle.ts","lineNumber":113,"sourceCode":"}\n\nfunction validateRemotePath(p) {\n  const s = String(p || '')\n\n  if (!s) {\n    throw new Error('Remote path must not be empty.')\n  }\n\n  // eslint-disable-next-line no-control-regex -- deliberately reject NUL in remote paths\n  if (/[\\x00\\n\\r]/.test(s)) {\n    throw new Error('Unsafe remote path: contains NUL or newline.')\n  }\n\n  if (s === '~' || s.startsWith('~/') || s.startsWith('/')) {\n    return\n  }\n\n  throw new Error(`Remote path must be absolute or start with ~/: \"${s}\"`)\n}\n\nfunction expandRemotePath(p) {\n  validateRemotePath(p)\n\n  if (p === '~') {\n    return '\"$HOME\"'\n  }\n\n  if (p.startsWith('~/')) {\n    return '\"$HOME\"' + shq(p.slice(1))\n  }\n\n  return shq(p)\n}\n\n// Resolve the remote hermes executable. An EXPLICIT path is honored strictly\n// (throws a path-naming error if not executable — never silently falls back to a","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/electron/remote-lifecycle.ts#L95-L131","documentation":"Thrown by validateRemotePath() when the path is non-empty and free of NUL/newlines but is neither absolute (leading /) nor home-relative (~ or ~/...). expandRemotePath() only supports those two forms because it rewrites them to '\"$HOME\"'-anchored or literal absolute strings inside a shell command; anything else is ambiguous on the remote host.","triggerScenarios":"Calling expandRemotePath('hermes'), expandRemotePath('./logs'), or expandRemotePath('x/y') — any bare or dot-relative path. The validator accepts only '~', '~/...', or '/...' and rejects everything else.","commonSituations":"Users entering a project-relative directory like 'hermes-agent' in a remote workdir setting; reusing a local relative cwd as a remote path; a form placeholder suggesting 'hermes' without the ~/ prefix.","solutions":["Use an absolute path (/opt/hermes) or a home-relative path (~/hermes) in the remote path setting.","If the value is meant to be relative to the remote home, prefix it: `~/${value}`.","Update the settings UI hint/validation to require the ~/ or / prefix at entry time."],"exampleFix":"// before\nexpandRemotePath(userPath) // userPath = 'hermes'\n\n// after\nconst p = userPath.startsWith('/') || userPath.startsWith('~') ? userPath : `~/${userPath}`\nexpandRemotePath(p)","handlingStrategy":"validation","validationCode":"function isSupportedRemotePathForm(s: string): boolean {\n  return s === '~' || s.startsWith('~/') || s.startsWith('/')\n}\n\nconst p = String(config.path ?? '')\nif (!isSupportedRemotePathForm(p)) {\n  // normalize bare relative names to home-relative before validation\n  config.path = `~/${p}`\n}","typeGuard":"function isAbsoluteOrHomeRelative(p: unknown): p is string {\n  return typeof p === 'string' && (p === '~' || p.startsWith('~/') || p.startsWith('/'))\n}","tryCatchPattern":"try {\n  return expandRemotePath(p)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('must be absolute or start with ~/')) {\n    return expandRemotePath(`~/${p}`) // retry with home-relative normalization\n  }\n  throw e\n}","preventionTips":["Show the '~/ or / required' rule in the remote path field placeholder and validate on save.","Auto-prefix '~/' for bare relative inputs in the settings form.","Never feed local cwd values (often relative) into remote path expansion without mapping."],"tags":["validation","remote","path"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}