{"record":{"id":"5b0f20d57911be7d","repo":"sinelaw/fresh","slug":"no-such-folder-folderid","errorCode":null,"errorMessage":"no such folder: ${folderId}","messagePattern":"no such folder: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/plugins/orchestrator.ts","lineNumber":10615,"sourceCode":"  renameWorkspace(s, typeof name === \"string\" ? name : \"\");\n  refreshOpenDialog();\n  return true;\n}\n\nfunction apiMoveWorkspace(\n  target: string | number,\n  folderId: string | null,\n): boolean {\n  const s = resolveWorkspace(target);\n  if (!s) return false;\n  rejectPending(s, \"filed\");\n  // An unknown folder id throws rather than silently filing at the top\n  // level: `assignSessionToFolder` would happily record it, and the row\n  // would then read as unfiled because `folderOfSession` drops assignments\n  // to folders that don't exist — a move that reports success and does\n  // nothing is the worst of both.\n  if (folderId !== null && !folderById(folderId)) {\n    throw new Error(`no such folder: ${folderId}`);\n  }\n  assignSessionToFolder(s.id, folderId);\n  refreshDockTree();\n  return true;\n}\n\nfunction apiListFolders(): FolderSummary[] {\n  const out: FolderSummary[] = [];\n  // Depth-first from the top level, so parents precede their children and\n  // siblings come out in the order `childFoldersOf` gives the dock.\n  const walk = (parent: string | null, depth: number): void => {\n    for (const f of childFoldersOf(parent)) {\n      out.push({ folderId: f.id, name: f.name, parent: f.parent ?? null, depth });\n      walk(f.id, depth + 1);\n    }\n  };\n  walk(null, 0);\n  return out;","sourceCodeStart":10597,"sourceCodeEnd":10633,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/plugins/orchestrator.ts#L10597-L10633","documentation":"Thrown when assigning a session to a folder whose id does not exist. The API deliberately throws instead of silently recording the assignment, because folderOfSession drops assignments to non-existent folders — so a silent write would report success while the row still reads as unfiled. Throwing surfaces the bad id immediately.","triggerScenarios":"Calling assignSessionToFolder (or the dock move-file API) with a folderId that was deleted, was never created, or was mistyped/stale from a previous dock snapshot; passing a non-null id when the intent was to unfile (which requires null).","commonSituations":"UI holding a stale folder id after another client deleted the folder; scripts caching folder ids across runs; passing an empty object/string coerced into a truthy id instead of null to unfile.","solutions":["Verify the folder id against the list returned by the folder-tree/list API before assigning","Pass null explicitly to unfile a session instead of a stale or empty id","Re-fetch the current folder list after delete/rename operations and refresh cached ids"],"exampleFix":"// before\napi.assignSessionToFolder(sessionId, lastKnownFolderId);\n// after\nconst folders = api.listFolders();\nif (!folders.some(f => f.id === lastKnownFolderId)) {\n  lastKnownFolderId = null;\n}\napi.assignSessionToFolder(sessionId, lastKnownFolderId);","handlingStrategy":"validation","validationCode":"const folderExists = (id) => id === null || api.listFolders().some(f => f.id === id);\nif (!folderExists(folderId)) throw new Error(`unknown folder ${folderId}`);","typeGuard":"function isKnownFolder(id, folders) {\n  return id === null || folders.some(f => f.id === id);\n}","tryCatchPattern":"try {\n  api.assignSessionToFolder(sessionId, folderId);\n} catch (e) {\n  if (String(e).startsWith(\"no such folder\")) {\n    folderId = null; // unfile instead of failing\n    api.assignSessionToFolder(sessionId, folderId);\n  } else throw e;\n}","preventionTips":["Refresh cached folder ids after any delete/rename","Use null (not \"\" or a sentinel string) to unfile a session","Resolve folder ids by name from a fresh list rather than hardcoding ids","Treat another-client deletions as possible and re-validate before writes"],"tags":["typescript","folder-assignment","not-found"],"backgroundTag":"entity-not-found","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}