{"record":{"id":"d7cddea43cade829","repo":"NousResearch/hermes-agent","slug":"that-project-has-no-folder-to-move-into","errorCode":null,"errorMessage":"That project has no folder to move into","messagePattern":"That project has no folder to move into","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/src/store/projects.ts","lineNumber":534,"sourceCode":"  branch?: null | string\n  cwd?: string\n  git_repo_root?: null | string\n}\n\n// Re-home a stored session into another project's root folder — the fix for a\n// chat created in the wrong directory. The backend replaces cwd + git identity\n// (so the tree's grouping follows) and re-anchors any live agent bound to the\n// row; here we mirror the move into the `$sessions` cache so both the flat list\n// and the grouped tree reflect it before the next authoritative refresh.\nexport async function moveSessionToProject(\n  sessionId: string,\n  projectId: string,\n  profile?: null | string\n): Promise<void> {\n  const cwd = projectRootCwd($projectTree.get().find(node => node.id === projectId))\n\n  if (!cwd) {\n    throw new Error(translateNow('sidebar.projects.moveNoFolder'))\n  }\n\n  const res = await gatewayRequest<WorkspaceMovePayload>('session.workspace.move', {\n    cwd,\n    session_key: sessionId,\n    ...(profile ? { profile } : {})\n  })\n\n  const moved = res.cwd || cwd\n  setSessions(prev =>\n    prev.map(s =>\n      sessionMatchesStoredId(s, sessionId)\n        ? { ...s, cwd: moved, git_branch: res.branch ?? null, git_repo_root: res.git_repo_root ?? null }\n        : s\n    )\n  )\n  void refreshProjectTree()\n}","sourceCodeStart":516,"sourceCodeEnd":552,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/src/store/projects.ts#L516-L552","documentation":"Thrown by moveSessionToProject when the project node selected for a session move has no folder cwd to anchor it. The desktop store resolves the target project's root working directory via projectRootCwd() from the $projectTree; if the node is missing (id not found) or is not a folder-backed project, cwd is null and the move is refused before any gateway RPC is issued. The backend's session.workspace.move requires a real cwd because it re-anchors both the session's directory grouping and any live agent.","triggerScenarios":"Calling moveSessionToProject(sessionId, projectId) where projectId does not exist in $projectTree.get(), or where the project node is a virtual/non-folder grouping that projectRootCwd() maps to null (e.g. a profile-level or synthetic node with no folder root).","commonSituations":"Stale project tree after the backend refreshed projects (node id changed or was removed), racing a project deletion with a drag-and-drop move in the sidebar, or passing a project id from a different profile.","solutions":["Verify the projectId exists in $projectTree.get() before calling, and refresh the tree if it is stale.","Ensure the target node is a folder-backed project (has a root cwd) — virtual groupings cannot accept moved sessions.","Guard the call with projectRootCwd(...) yourself and surface a 'pick a folder-backed project' message instead of letting it throw.","Check the profile argument matches the tree you searched — a mismatched profile yields a node miss."],"exampleFix":"// before\nawait moveSessionToProject(sessionId, projectId)\n\n// after\nconst node = $projectTree.get().find(n => n.id === projectId)\nif (!node || !projectRootCwd(node)) {\n  toast('Pick a project that has a folder.')\n} else {\n  await moveSessionToProject(sessionId, projectId)\n}","handlingStrategy":"validation","validationCode":"import { $projectTree } from '.../store/projects'\nimport { projectRootCwd } from '.../store/projects'\n\nfunction canMoveToProject(projectId: string): boolean {\n  const node = $projectTree.get().find(n => n.id === projectId)\n  return Boolean(projectRootCwd(node))\n}","typeGuard":"function isFolderProject(node: ProjectNode | undefined): node is ProjectNode & { cwd: string } {\n  return Boolean(node && projectRootCwd(node))\n}","tryCatchPattern":"try {\n  await moveSessionToProject(sessionId, projectId)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('no folder')) refreshProjectTree()\n  else throw e\n}","preventionTips":["Refresh $projectTree before user-initiated move/drop actions.","Only render folder-backed projects as valid drop targets in the sidebar.","Pass profile-consistent ids — never ids sourced from another profile's tree."],"tags":["desktop","sessions","projects","validation"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}