vercel/ai · error

Pi session has been stopped.

Error message

Pi session has been stopped.

What it means

Once a Pi session has been stopped via stop(), any new prompt turn is rejected because the adapter no longer accepts work for a terminated session. The guard at the top of the prompt-turn path throws immediately when `stopped` is true.

Source

Thrown at packages/harness-pi/src/pi-session.ts:1071

    return resourcesReloaded;
  }

  /*
   * Drive one turn against the Pi session and return the control surface.
   * Shared by `doPromptTurn` (a fresh user prompt) and `doContinueTurn` (an empty
   * prompt that asks Pi to continue its own thread after a rerun resume).
   */
  async function runTurn(turnOpts: {
    text: string;
    model?: string;
    skills: ReadonlyArray<HarnessV1Skill>;
    tools: ReadonlyArray<HarnessV1ToolSpec>;
    instructions?: string;
    emit: (part: HarnessV1StreamPart) => void;
    abortSignal?: AbortSignal;
  }): Promise<HarnessV1PromptControl> {
    if (stopped) {
      throw new Error('Pi session has been stopped.');
    }

    const skillWriteResult = await writePiSkills({
      sandbox: toolSafeSandboxSession,
      sandboxHomeDir,
      skills: turnOpts.skills,
      abortSignal: turnOpts.abortSignal,
    });
    harnessSkills = createHarnessPiSkills({
      skills: turnOpts.skills,
      sandboxSkillRootDir,
    });
    if (piSession != null && skillWriteResult.changed) {
      await reloadResourcesOnly();
    }

    const userTools = turnOpts.tools;
    currentEmit = turnOpts.emit;

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Create a new session (createPi) or resume from persisted state instead of prompting the stopped handle
  2. Track stop state in your app before issuing further prompts
  3. If the stop was unintentional, avoid calling stop() until the run is complete

Example fix

// before
await session.stop();
await session.prompt({ prompt: 'one more' }); // throws: stopped
// after
await session.stop();
const session2 = await pi.resumeSession({ ...state });
await session2.prompt({ prompt: 'one more' });
Defensive patterns

Strategy: type-guard

Validate before calling

// track stop state yourself
let stopped = false;
const guard = () => { if (stopped) throw new Error('session stopped locally'); };

Type guard

function isStopped(err: unknown): boolean {
  return err instanceof Error && err.message === 'Pi session has been stopped.';
}

Try / catch

try {
  await session.prompt(opts);
} catch (e) {
  if (isStopped(e)) {
    const fresh = await pi.resumeSession({ ...savedState });
    return fresh.prompt(opts);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling prompt/doPromptTurn after a previous call to `stop()` on the same session handle, or on a handle whose session was stopped in a prior lifecycle step.

Common situations: Reusing a stale session object after an intentional stop; a UI that keeps a reference after the user clicked 'stop'; error-retry logic retrying prompts on a stopped session.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/84f9505bd80ef542. Report an issue: GitHub.