openclaw/openclaw · warning · Error

Pi session list parameters must be an object

Error message

Pi session list parameters must be an object

What it means

Thrown by parseListParams when the list parameters value is supplied (not undefined/null) but is not a plain object (record). Arrays, strings, numbers, booleans, and any non-record primitive are rejected. The catalog list path requires either no params (defaults) or a record with the recognised keys.

Source

Thrown at extensions/acpx/src/pi-session-catalog.ts:165

      }
      if (part.type === "text" && typeof part.text === "string") {
        return [part.text];
      }
      if (part.type === "image") {
        const mimeType = optionalPiString(part.mimeType, 128);
        return [mimeType ? `[image: ${mimeType}]` : "[image]"];
      }
      return [];
    })
    .join("\n");
}

function parseListParams(value: unknown): { searchTerm?: string; limit: number; cursor?: string } {
  if (value === undefined || value === null) {
    return { limit: DEFAULT_PAGE_LIMIT };
  }
  if (!isRecord(value)) {
    throw new Error("Pi session list parameters must be an object");
  }
  const unknown = Object.keys(value).find(
    (key) => !["searchTerm", "limit", "cursor"].includes(key),
  );
  if (unknown) {
    throw new Error(`unknown Pi session list parameter: ${unknown}`);
  }
  const searchTerm = optionalPiString(value.searchTerm, MAX_SEARCH_LENGTH);
  if (value.searchTerm !== undefined && !searchTerm) {
    throw new Error("searchTerm is invalid");
  }
  const cursor = optionalRawCursor(value.cursor);
  return {
    limit: boundedLimit(value.limit),
    ...(searchTerm ? { searchTerm } : {}),
    ...(cursor ? { cursor } : {}),
  };
}

View on GitHub (pinned to 01804a7531)

Solutions

  1. Pass either undefined (defaults) or a plain object with keys from { searchTerm, limit, cursor }.
  2. If you received params as JSON, parse it first: JSON.parse(paramsJSON).
  3. Wrap bare values: use { searchTerm: value } instead of value.
  4. Validate with isRecord at the boundary before calling list.

Example fix

// before
await listLocalPiSessionPage(req.body); // body is a JSON string
// after
await listLocalPiSessionPage(JSON.parse(req.body));
Defensive patterns

Strategy: type-guard

Validate before calling

import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
function coerceListParams(value: unknown) {
  if (value === undefined || value === null) return undefined;
  if (!isRecord(value)) throw new TypeError("Pi session list parameters must be an object");
  return value;
}

Type guard

import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
function isPiListParams(value: unknown): value is Record<string, unknown> {
  return value === undefined || value === null || isRecord(value);
}

Prevention

When it happens

Trigger: Calling listLocalPiSessionPage with a JSON string instead of a parsed object. Passing an array of params. Passing a primitive (e.g. a bare search string) instead of { searchTerm: string }. A serialisation layer forgot to JSON.parse before invoking.

Common situations: A node-command handler receives paramsJSON and the caller forgets to parse it into an object. A REST/IPC boundary sends the params as a JSON string. A naive client passes the search term directly instead of wrapping it.

Related errors


AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12). Data as JSON: /api/errors/73beba78e736fc86. Report an issue: GitHub.