{"record":{"id":"12c4580d1ec8f936","repo":"openclaw/openclaw","slug":"codex-session-catalog-parameters-must-be-an-object","errorCode":null,"errorMessage":"Codex session catalog parameters must be an object","messagePattern":"Codex session catalog parameters must be an object","errorType":"validation","errorClass":"CatalogParamsError","httpStatus":null,"severity":"error","filePath":"extensions/codex/src/session-catalog-parsing.ts","lineNumber":216,"sourceCode":"  if (trimmed.length > maxLength) {\n    throw new CatalogParamsError(`${key} must be at most ${maxLength} characters`);\n  }\n  return trimmed;\n}\n\nexport function requireOnlyKeys(\n  params: Record<string, unknown>,\n  allowed: ReadonlySet<string>,\n): void {\n  const unknown = Object.keys(params).find((key) => !allowed.has(key));\n  if (unknown) {\n    throw new CatalogParamsError(`unknown Codex session catalog parameter: ${unknown}`);\n  }\n}\n\nexport function readPageParams(value: unknown): CodexSessionCatalogPageParams {\n  if (!isRecord(value)) {\n    throw new CatalogParamsError(\"Codex session catalog parameters must be an object\");\n  }\n  const params = value;\n  requireOnlyKeys(params, new Set([\"cursor\", \"limit\", \"searchTerm\", \"cwd\"]));\n  const cursor = readBoundedOptionalString(params, \"cursor\", MAX_CURSOR_LENGTH);\n  const searchTerm = readBoundedOptionalString(params, \"searchTerm\", MAX_SEARCH_LENGTH);\n  const cwd = readBoundedOptionalString(params, \"cwd\", MAX_CWD_LENGTH);\n  return {\n    limit: normalizeLimit(params.limit, \"limit\"),\n    ...(cursor ? { cursor } : {}),\n    ...(searchTerm ? { searchTerm } : {}),\n    ...(cwd ? { cwd } : {}),\n  };\n}\n\nexport function readGatewayParams(value: unknown): CodexSessionCatalogParams {\n  if (value !== undefined && !isRecord(value)) {\n    throw new CatalogParamsError(\"Codex session catalog parameters must be an object\");\n  }","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/codex/src/session-catalog-parsing.ts#L198-L234","documentation":"Thrown as CatalogParamsError by readPageParams in session-catalog-parsing.ts:216 when the page-params value is not a record (object). Page params must be a plain object so its keys can be validated; arrays, strings, numbers, booleans, and null all fail the isRecord check.","triggerScenarios":"Passing page params as a JSON string (not yet parsed), an array of params, a single string cursor, null, or a number. Undefined would also fail here because readPageParams requires the value to be a record (no default-to-empty unlike readGatewayParams).","commonSituations":"Client forwards a JSON.parse'd array instead of an object; passes null explicitly; sends the cursor string directly instead of wrapping it in {cursor: ...}.","solutions":["Always pass a plain object (at minimum {}) to readPageParams.","If you have a bare cursor, wrap it: {cursor: cursorValue}.","JSON.parse the payload before calling if it arrived as a string, and assert it is an object.","Use readGatewayParams instead if you need undefined-to-default behaviour."],"exampleFix":"// before\nreadPageParams(JSON.stringify({ cursor })); // throws\nreadPageParams(null); // throws\n\n// after\nreadPageParams(typeof raw === 'string' ? JSON.parse(raw) : (raw ?? {}));\n// or simply\nreadPageParams({ cursor });","handlingStrategy":"type-guard","validationCode":"// Ensure page params is a plain object before calling readPageParams.\nfunction asPageParams(value: unknown): Record<string, unknown> {\n  return value && typeof value === 'object' && !Array.isArray(value)\n    ? value as Record<string, unknown>\n    : {};\n}\n\nreadPageParams(asPageParams(raw));","typeGuard":"function isParamsObject(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value);\n}","tryCatchPattern":null,"preventionTips":["Always pass a plain object (at minimum {}) to readPageParams.","JSON.parse string payloads first and assert the result is a non-array object.","Wrap bare cursors as { cursor: value } rather than passing the string directly.","Use readGatewayParams if you need undefined-to-default behaviour."],"tags":["codex","session-catalog","validation","params","type"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}