paperclipai/paperclip · error

There is no current session goal to edit.

Error message

There is no current session goal to edit.

What it means

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.

Source

Thrown at ui/src/components/task-chat/RunnerGoalWidget.tsx:118

        throw new Error(current.capability.reason ?? "Session goals are unsupported by this agent.");
      }
      await mutation.mutateAsync({
        requestId: requestId(),
        agentId: current.agentId,
        expectedRevision: expectedRevision ?? current.revision,
        action,
        ...(objective ? { objective } : {}),
        ...(action === "replace" ? { confirmReplace } : {}),
      });
    } catch (error) {
      setActionError(error instanceof Error ? error.message : "The goal action could not be applied.");
      throw error;
    }
  }, [mutation, query]);

  const edit = useCallback(async () => {
    const current = query.data ?? (await query.refetch()).data;
    if (!current?.goal) throw new Error("There is no current session goal to edit.");
    mutation.reset();
    setActionError(null);
    setExpanded(true);
    setDialog({ action: "edit", objective: current.goal.objective, revision: current.revision });
  }, [query, mutation]);

  const executeComposerCommand = useCallback(async (command: RunnerGoalComposerCommand) => {
    if (command.action === "focus") {
      const current = query.data ?? (await query.refetch()).data;
      if (!current?.goal && !current?.pendingAction) {
        throw new Error("Add an objective after /goal to start a goal.");
      }
      setExpanded(true);
      return;
    }
    if (command.action === "edit") {
      await edit();
      return;

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check the current goal exists (via the widget UI) before invoking edit.
  2. Set a goal first with the set-goal action, then edit it.
  3. If the goal should exist, refresh the session data and retry; investigate the goals API if it still returns empty.

Example fix

// before
await control.edit(); // throws if no goal
// after
const current = await control.refetch();
if (current?.goal) await control.edit();
else await control.startNewGoal(); // or surface a friendly message
Defensive patterns

Strategy: validation

Validate before calling

const current = await query.refetch().then(r => r.data);
if (!current?.goal) { showEmptyGoalHint(); return; }

Type guard

function hasGoal(s: { goal?: { objective: string } | null } | null | undefined): s is { goal: { objective: string } } {
  return !!s?.goal && typeof s.goal.objective === "string";
}

Try / catch

try {
  await control.edit();
} catch (e) {
  if (e instanceof Error && e.message.includes("no current session goal")) {
    promptCreateGoal();
  } else throw e;
}

Prevention

When it happens

Trigger: 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`.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/a6d4ff99db29130f. Report an issue: GitHub.