openclaw/openclaw · error · Error

Codex ${method} returned an invalid nextCursor

Error message

Codex ${method} returned an invalid nextCursor

What it means

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.

Source

Thrown at extensions/codex/src/supervision-tools.ts:173

  request?: EndpointRequest;
  /** Only a trusted standalone MCP adapter may opt into the shipped env gates. */
  useLegacyMcpPolicyEnv?: boolean;
};

function asRecordArray(value: unknown): Record<string, unknown>[] {
  return Array.isArray(value) ? value.filter(isRecord) : [];
}

function readCompatNextCursor(value: unknown, method: string): string | undefined {
  if (value === null || value === undefined) {
    return undefined;
  }
  if (
    typeof value !== "string" ||
    value.trim().length === 0 ||
    value.length > MAX_COMPAT_CURSOR_LENGTH
  ) {
    throw new Error(`Codex ${method} returned an invalid nextCursor`);
  }
  return value;
}

function readCompatThreadId(value: unknown, method: string, index: number): string {
  if (
    typeof value !== "string" ||
    value.trim().length === 0 ||
    value.length > MAX_COMPAT_THREAD_ID_LENGTH
  ) {
    throw new Error(`Codex ${method} returned an invalid thread id at data[${index}]`);
  }
  return value;
}

function readLoadedThreadIds(data: unknown[]): string[] {
  if (data.length > PAGE_LIMIT) {
    throw new Error(`Codex thread/loaded/list returned more than ${PAGE_LIMIT} entries`);

View on GitHub (pinned to 01804a7531)

Solutions

  1. Confirm the Codex app-server version is compatible with this OpenClaw build.
  2. If the cursor is genuinely too long or wrong type, capture the raw app-server response and report it.
  3. Update or roll back the app-server to a version whose cursor shape matches.

Example fix

// before: app-server returns nextCursor: 42 or nextCursor: ''
const page = await endpoint.request('thread/list', { ... }); // throws 1196 in compat layer

// after: ensure the app-server returns a non-empty string cursor <= 4096 chars
// (fix is server-side; client treats invalid cursor as a hard error by design)
Defensive patterns

Strategy: type-guard

Validate before calling

const MAX_COMPAT_CURSOR_LENGTH = 4096;
function readCompatNextCursor(value) {
  if (value === null || value === undefined) return undefined;
  if (typeof value !== 'string' || value.trim().length === 0 || value.length > MAX_COMPAT_CURSOR_LENGTH) {
    throw new Error('app-server returned an invalid nextCursor');
  }
  return value;
}

Type guard

function isValidNextCursor(value: unknown): value is string {
  return typeof value === 'string' && value.trim().length > 0 && value.length <= 4096;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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