{"record":{"id":"dc342715707c8bf7","repo":"openclaw/openclaw","slug":"codex-method-returned-an-invalid-nextcursor","errorCode":null,"errorMessage":"Codex ${method} returned an invalid nextCursor","messagePattern":"Codex (.+?) returned an invalid nextCursor","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extensions/codex/src/supervision-tools.ts","lineNumber":173,"sourceCode":"  request?: EndpointRequest;\n  /** Only a trusted standalone MCP adapter may opt into the shipped env gates. */\n  useLegacyMcpPolicyEnv?: boolean;\n};\n\nfunction asRecordArray(value: unknown): Record<string, unknown>[] {\n  return Array.isArray(value) ? value.filter(isRecord) : [];\n}\n\nfunction readCompatNextCursor(value: unknown, method: string): string | undefined {\n  if (value === null || value === undefined) {\n    return undefined;\n  }\n  if (\n    typeof value !== \"string\" ||\n    value.trim().length === 0 ||\n    value.length > MAX_COMPAT_CURSOR_LENGTH\n  ) {\n    throw new Error(`Codex ${method} returned an invalid nextCursor`);\n  }\n  return value;\n}\n\nfunction readCompatThreadId(value: unknown, method: string, index: number): string {\n  if (\n    typeof value !== \"string\" ||\n    value.trim().length === 0 ||\n    value.length > MAX_COMPAT_THREAD_ID_LENGTH\n  ) {\n    throw new Error(`Codex ${method} returned an invalid thread id at data[${index}]`);\n  }\n  return value;\n}\n\nfunction readLoadedThreadIds(data: unknown[]): string[] {\n  if (data.length > PAGE_LIMIT) {\n    throw new Error(`Codex thread/loaded/list returned more than ${PAGE_LIMIT} entries`);","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/codex/src/supervision-tools.ts#L155-L191","documentation":"Thrown by readCompatNextCursor in the supervision-tools compat layer when an app-server response's nextCursor field is present but invalid: not a string, empty/whitespace, or longer than MAX_COMPAT_CURSOR_LENGTH (4096). The method name is interpolated so the message names which app-server RPC produced the bad cursor. This guards against malformed pagination from a Codex app-server speaking an unexpected dialect.","triggerScenarios":"An app-server returns nextCursor as a number, object, empty string, or a >4KB token; version skew between the supervision tools' expected cursor shape and the app-server's actual shape; a proxied app-server mangled the field.","commonSituations":"Codex app-server upgraded to a newer protocol that uses a different cursor encoding; a forked/custom app-server returns non-string cursors; truncated JSON produced an empty cursor.","solutions":["Confirm the Codex app-server version is compatible with this OpenClaw build.","If the cursor is genuinely too long or wrong type, capture the raw app-server response and report it.","Update or roll back the app-server to a version whose cursor shape matches."],"exampleFix":"// before: app-server returns nextCursor: 42 or nextCursor: ''\nconst page = await endpoint.request('thread/list', { ... }); // throws 1196 in compat layer\n\n// after: ensure the app-server returns a non-empty string cursor <= 4096 chars\n// (fix is server-side; client treats invalid cursor as a hard error by design)","handlingStrategy":"type-guard","validationCode":"const MAX_COMPAT_CURSOR_LENGTH = 4096;\nfunction readCompatNextCursor(value) {\n  if (value === null || value === undefined) return undefined;\n  if (typeof value !== 'string' || value.trim().length === 0 || value.length > MAX_COMPAT_CURSOR_LENGTH) {\n    throw new Error('app-server returned an invalid nextCursor');\n  }\n  return value;\n}","typeGuard":"function isValidNextCursor(value: unknown): value is string {\n  return typeof value === 'string' && value.trim().length > 0 && value.length <= 4096;\n}","tryCatchPattern":null,"preventionTips":["Use a Codex app-server version compatible with this OpenClaw build.","If cursors exceed 4096 chars or are non-string, capture the raw app-server response and report it.","Treat invalid cursors as a hard error rather than silently paging — the compat layer is correct to reject them."],"tags":["codex","app-server","compat","cursor","pagination","supervision"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}