mem0ai/mem0 · info · Error

Cancelled

Error message

Cancelled

What it means

Cooperative-cancellation error thrown by the pi-agent-plugin memory tool's 'search' action when the caller-provided AbortSignal is already aborted before the (potentially expensive) Mem0 search request runs. The tool checks signal.aborted at the start of each action to stop work promptly when the user or agent cancels the turn.

Source

Thrown at integrations/pi-agent-plugin/src/memory/tools.ts:57

interface ToolParams {
  action: "search" | "add" | "get_all" | "update" | "delete" | "delete_all";
  query?: string;
  content?: string;
  memory_id?: string;
  scope?: Scope;
}

export function buildToolExecute(
  mem0: MemoryClient,
  scopeCtx: ScopeContext,
  defaultScope: Scope,
) {
  return async (params: ToolParams, signal?: AbortSignal) => {
    const scope = params.scope ?? defaultScope;

    switch (params.action) {
      case "search": {
        if (signal?.aborted) throw new Error("Cancelled");
        if (!params.query) throw new Error("query is required for search");
        const filters = resolveSearchFilters(scope, scopeCtx);
        const result = await mem0.search(params.query, { filters });
        const memories = result.results ?? [];
        return {
          content: [{ type: "text" as const, text: truncateOutput(formatMemoryList(memories)) }],
          details: { matchCount: memories.length },
        };
      }

      case "add": {
        if (signal?.aborted) throw new Error("Cancelled");
        if (!params.content) throw new Error("content is required for add");
        const addParams = resolveAddParams(scope, scopeCtx);
        const result = await mem0.add(
          [{ role: "user", content: params.content }],
          { ...addParams, customCategories: DEFAULT_CUSTOM_CATEGORIES },
        );

View on GitHub (pinned to 001c235229)

Solutions

  1. Treat as control flow, not a bug: catch it and stop the calling workflow without retrying.
  2. If cancellation is unexpected, audit where the AbortSignal originates (agent runtime / HTTP request) — something upstream aborted the turn.
  3. Don't call the tool after awaiting a cancelled operation; check signal.aborted in your own loop first.
Defensive patterns

Strategy: try-catch

Validate before calling

if (signal?.aborted) return { content: [{ type: 'text', text: 'cancelled' }], details: {} };

Try / catch

try {
  return await toolExecute(params, signal);
} catch (err) {
  if ((err as Error).message === 'Cancelled') return { cancelled: true };
  throw err;
}

Prevention

When it happens

Trigger: The agent runtime passes an AbortSignal that was aborted (user pressed Esc / cancelled the tool call / turn timeout) and the tool executor still invokes the search action with that signal.

Common situations: User cancels while a tool call is queued; agent framework aborts in-flight tools when a newer turn starts; signal propagated from a request that already timed out.

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/38cae32309d1e315. Report an issue: GitHub.