{"record":{"id":"73beba78e736fc86","repo":"openclaw/openclaw","slug":"pi-session-list-parameters-must-be-an-object","errorCode":null,"errorMessage":"Pi session list parameters must be an object","messagePattern":"Pi session list parameters must be an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"extensions/acpx/src/pi-session-catalog.ts","lineNumber":165,"sourceCode":"      }\n      if (part.type === \"text\" && typeof part.text === \"string\") {\n        return [part.text];\n      }\n      if (part.type === \"image\") {\n        const mimeType = optionalPiString(part.mimeType, 128);\n        return [mimeType ? `[image: ${mimeType}]` : \"[image]\"];\n      }\n      return [];\n    })\n    .join(\"\\n\");\n}\n\nfunction parseListParams(value: unknown): { searchTerm?: string; limit: number; cursor?: string } {\n  if (value === undefined || value === null) {\n    return { limit: DEFAULT_PAGE_LIMIT };\n  }\n  if (!isRecord(value)) {\n    throw new Error(\"Pi session list parameters must be an object\");\n  }\n  const unknown = Object.keys(value).find(\n    (key) => ![\"searchTerm\", \"limit\", \"cursor\"].includes(key),\n  );\n  if (unknown) {\n    throw new Error(`unknown Pi session list parameter: ${unknown}`);\n  }\n  const searchTerm = optionalPiString(value.searchTerm, MAX_SEARCH_LENGTH);\n  if (value.searchTerm !== undefined && !searchTerm) {\n    throw new Error(\"searchTerm is invalid\");\n  }\n  const cursor = optionalRawCursor(value.cursor);\n  return {\n    limit: boundedLimit(value.limit),\n    ...(searchTerm ? { searchTerm } : {}),\n    ...(cursor ? { cursor } : {}),\n  };\n}","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/acpx/src/pi-session-catalog.ts#L147-L183","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass either undefined (defaults) or a plain object with keys from { searchTerm, limit, cursor }.","If you received params as JSON, parse it first: JSON.parse(paramsJSON).","Wrap bare values: use { searchTerm: value } instead of value.","Validate with isRecord at the boundary before calling list."],"exampleFix":"// before\nawait listLocalPiSessionPage(req.body); // body is a JSON string\n// after\nawait listLocalPiSessionPage(JSON.parse(req.body));","handlingStrategy":"type-guard","validationCode":"import { isRecord } from \"openclaw/plugin-sdk/string-coerce-runtime\";\nfunction coerceListParams(value: unknown) {\n  if (value === undefined || value === null) return undefined;\n  if (!isRecord(value)) throw new TypeError(\"Pi session list parameters must be an object\");\n  return value;\n}","typeGuard":"import { isRecord } from \"openclaw/plugin-sdk/string-coerce-runtime\";\nfunction isPiListParams(value: unknown): value is Record<string, unknown> {\n  return value === undefined || value === null || isRecord(value);\n}","tryCatchPattern":null,"preventionTips":["Parse JSON params before passing them to listLocalPiSessionPage.","Pass undefined for defaults rather than a stringified object.","Validate with isRecord at the boundary."],"tags":["pi-session-catalog","params-validation","list","acpx"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}