{"record":{"id":"a6d4ff99db29130f","repo":"paperclipai/paperclip","slug":"there-is-no-current-session-goal-to-edit","errorCode":null,"errorMessage":"There is no current session goal to edit.","messagePattern":"There is no current session goal to edit\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ui/src/components/task-chat/RunnerGoalWidget.tsx","lineNumber":118,"sourceCode":"        throw new Error(current.capability.reason ?? \"Session goals are unsupported by this agent.\");\n      }\n      await mutation.mutateAsync({\n        requestId: requestId(),\n        agentId: current.agentId,\n        expectedRevision: expectedRevision ?? current.revision,\n        action,\n        ...(objective ? { objective } : {}),\n        ...(action === \"replace\" ? { confirmReplace } : {}),\n      });\n    } catch (error) {\n      setActionError(error instanceof Error ? error.message : \"The goal action could not be applied.\");\n      throw error;\n    }\n  }, [mutation, query]);\n\n  const edit = useCallback(async () => {\n    const current = query.data ?? (await query.refetch()).data;\n    if (!current?.goal) throw new Error(\"There is no current session goal to edit.\");\n    mutation.reset();\n    setActionError(null);\n    setExpanded(true);\n    setDialog({ action: \"edit\", objective: current.goal.objective, revision: current.revision });\n  }, [query, mutation]);\n\n  const executeComposerCommand = useCallback(async (command: RunnerGoalComposerCommand) => {\n    if (command.action === \"focus\") {\n      const current = query.data ?? (await query.refetch()).data;\n      if (!current?.goal && !current?.pendingAction) {\n        throw new Error(\"Add an objective after /goal to start a goal.\");\n      }\n      setExpanded(true);\n      return;\n    }\n    if (command.action === \"edit\") {\n      await edit();\n      return;","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/ui/src/components/task-chat/RunnerGoalWidget.tsx#L100-L136","documentation":"The RunnerGoalWidget's goal-control hook throws this when the user attempts to edit a session goal that does not exist. `edit()` refetches the current goal; if neither the cached nor fresh query data contains a `goal`, there is nothing to edit, so it rejects instead of opening an empty edit dialog. This guards the edit flow against operating on a missing objective/revision pair.","triggerScenarios":"Calling `edit()` (directly or via the /goal edit composer command) when the runner session has never had a goal set, the goal was cleared, or the refetch returns data with `goal: null/undefined`.","commonSituations":"User clicks Edit before ever setting a goal on a fresh session; goal was deleted by another actor and the cache is stale until refetch; API returns a session object with no goal field.","solutions":["Check the current goal exists (via the widget UI) before invoking edit.","Set a goal first with the set-goal action, then edit it.","If the goal should exist, refresh the session data and retry; investigate the goals API if it still returns empty."],"exampleFix":"// before\nawait control.edit(); // throws if no goal\n// after\nconst current = await control.refetch();\nif (current?.goal) await control.edit();\nelse await control.startNewGoal(); // or surface a friendly message","handlingStrategy":"validation","validationCode":"const current = await query.refetch().then(r => r.data);\nif (!current?.goal) { showEmptyGoalHint(); return; }","typeGuard":"function hasGoal(s: { goal?: { objective: string } | null } | null | undefined): s is { goal: { objective: string } } {\n  return !!s?.goal && typeof s.goal.objective === \"string\";\n}","tryCatchPattern":"try {\n  await control.edit();\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"no current session goal\")) {\n    promptCreateGoal();\n  } else throw e;\n}","preventionTips":["Disable the Edit button while `query.data?.goal` is falsy.","Refetch before rendering edit affordances so UI state matches the server.","Route first-time users to the create-goal flow instead of edit."],"tags":["ui","state-error","precondition-failed"],"backgroundTag":"invalid-state-transition","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}