paperclipai/paperclip · error · Error

ACPX runtime does not expose session goal controls

Error message

ACPX runtime does not expose session goal controls

What it means

The runtime host's controlGoal() delegates session goal set/pause/resume/clear to the underlying AcpxRuntimePort. This error is thrown when the wrapped runtime does not implement the optional controlGoal capability, so goal controls are unavailable for that runtime.

Source

Thrown at packages/paperclip-runner/src/drivers/acpx/runtime-host.ts:596

  async status(): Promise<AcpxModelStatus> {
    return structuredClone(await this.#runtime.getStatus());
  }

  goalCapability(): AcpxRuntimeGoalCapability | null {
    return this.#runtime.goalCapability?.() ?? null;
  }

  goalSnapshot(): AcpxRuntimeGoalSnapshot | null {
    return this.#runtime.goalSnapshot?.() ?? null;
  }

  async controlGoal(
    action: "set" | "pause" | "resume" | "clear",
    objective?: string,
  ): Promise<AcpxRuntimeGoalSnapshot | null> {
    if (!this.#runtime.controlGoal) {
      throw new Error("ACPX runtime does not expose session goal controls");
    }
    return await this.#runtime.controlGoal(action, objective);
  }

  startTurn(input: AcpxRuntimeTurnInput): AcpxRuntimeTurn {
    if (this.#closed || this.#closingStarted) {
      throw new Error("ACPX runtime host is closing");
    }
    if (this.#activeTurn) {
      throw new Error("ACPX runtime host already has an active turn");
    }
    const requestId = boundedRequestId(input.requestId);
    const text = boundedTurnText(input.text);
    const turn = this.#runtime.startTurn({
      text,
      requestId,
      ...(input.signal ? { signal: input.signal } : {}),
      ...(input.onElicitation ? { onElicitation: input.onElicitation } : {}),

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check that the runtime implementation in use supports goal controls before calling controlGoal (feature-detect host's runtime port)
  2. Upgrade the ACPX runtime/adapter package to a version exposing controlGoal
  3. Skip goal-control UI/actions when the capability is absent
  4. If injecting a custom AcpxRuntimePort (e.g. in tests), implement controlGoal

Example fix

// before
await host.controlGoal("set", objective);
// after
if (host.supportsGoalControls?.()) {
  await host.controlGoal("set", objective);
}
Defensive patterns

Strategy: validation

Validate before calling

if (typeof host.controlGoal !== "function") {
  // goal controls unavailable; skip
}

Type guard

function supportsGoalControls(runtime) {
  return typeof (runtime as AcpxRuntimePort).controlGoal === "function";
}

Try / catch

try {
  await host.controlGoal("set", objective);
} catch (err) {
  if (err.message.includes("session goal controls")) {
    return null; // capability absent
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling host.controlGoal("set"|"pause"|"resume"|"clear") when the underlying runtime instance was created without goal-control support, i.e. this.#runtime.controlGoal is undefined.

Common situations: Using an older or minimal ACPX runtime implementation that predates goal controls; a test/dummy runtime port that omits controlGoal; feature-flagged runtime builds where goal support is disabled.

Related errors


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