{"record":{"id":"3851efb9712e54c9","repo":"can1357/oh-my-pi","slug":"skip-must-be-a-non-negative-number","errorCode":null,"errorMessage":"skip must be a non-negative number","messagePattern":"skip must be a non-negative number","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/ast-grep.ts","lineNumber":206,"sourceCode":"\n\tconstructor(private readonly session: ToolSession) {}\n\n\tasync execute(\n\t\t_toolCallId: string,\n\t\tparams: typeof astGrepSchema.infer,\n\t\tsignal?: AbortSignal,\n\t\t_onUpdate?: AgentToolUpdateCallback<AstGrepToolDetails>,\n\t\t_context?: AgentToolContext,\n\t): Promise<AgentToolResult<AstGrepToolDetails>> {\n\t\treturn untilAborted(signal, async () => {\n\t\t\tconst pattern = params.pat.trim();\n\t\t\tif (pattern.length === 0) {\n\t\t\t\tthrow new ToolError(\"`pat` must be a non-empty pattern\");\n\t\t\t}\n\t\t\tconst patterns = [pattern];\n\t\t\tconst skip = params.skip === undefined ? 0 : Math.floor(params.skip);\n\t\t\tif (!Number.isFinite(skip) || skip < 0) {\n\t\t\t\tthrow new ToolError(\"skip must be a non-negative number\");\n\t\t\t}\n\t\t\tconst scopedPaths = toPathList(params.path);\n\t\t\tconst rawPaths = scopedPaths.length > 0 ? scopedPaths : [\".\"];\n\t\t\tconst scope = await resolveToolSearchScope({\n\t\t\t\trawPaths,\n\t\t\t\tcwd: this.session.cwd,\n\t\t\t\tinternalUrlAction: \"search\",\n\t\t\t\tsettings: this.session.settings,\n\t\t\t\tsignal,\n\t\t\t\tsessionFile: this.session.getSessionFile() ?? undefined,\n\t\t\t\tlocalProtocolOptions: this.session.localProtocolOptions,\n\t\t\t\tskills: this.session.skills,\n\t\t\t\tresolveExternalUrl: async rawPath => {\n\t\t\t\t\tconst target = parseReadUrlTarget(rawPath);\n\t\t\t\t\tif (!target) return undefined;\n\t\t\t\t\tconst materialized = await materializeReadUrlToFile(\n\t\t\t\t\t\tthis.session,\n\t\t\t\t\t\t{ path: target.path, raw: target.raw },","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/ast-grep.ts#L188-L224","documentation":"The `skip` pagination offset must be a finite, non-negative number. The tool floors the value and rejects NaN, ±Infinity, and negative numbers, since an invalid skip would corrupt result pagination for the underlying search.","triggerScenarios":"Calling AstGrepTool.execute with params.skip set to -1, NaN, Infinity, or -Infinity. (undefined is allowed and defaults to 0.)","commonSituations":"A model emits an out-of-range or symbolic value for `skip`; upstream code computes an offset that underflows (e.g. page * pageSize with a negative page); JSON parsing yields NaN from \"NaN\" input.","solutions":["Pass a non-negative integer for `skip` (or omit it to start at 0).","Clamp the offset: skip = Math.max(0, Math.floor(Number(rawSkip) || 0)).","Reject non-finite values at the caller boundary before invoking the tool."],"exampleFix":"// before\nawait tool.execute({ pat, skip: page * -10 }, ctx);\n\n// after\nconst skip = Math.max(0, Math.floor(page * 10));\nawait tool.execute({ pat, skip }, ctx);","handlingStrategy":"validation","validationCode":"const skip = params.skip === undefined ? 0 : Math.floor(params.skip);\nif (!Number.isFinite(skip) || skip < 0) throw new Error(\"skip must be a non-negative finite number\");","typeGuard":"function isValidSkip(v: unknown): v is number {\n  return typeof v === \"number\" && Number.isFinite(v) && v >= 0;\n}","tryCatchPattern":"try {\n  await tool.execute({ pat, skip }, ctx);\n} catch (e) {\n  if (e instanceof ToolError && e.message.includes(\"skip must be\")) {\n    // retry once with skip omitted (defaults to 0) or clamped value\n  } else throw e;\n}","preventionTips":["Clamp computed offsets: Math.max(0, Math.floor(x)).","Never derive skip from possibly-NaN arithmetic without a Number.isFinite check.","Omit `skip` entirely on the first page."],"tags":["validation","pagination","tool-input"],"backgroundTag":"invalid-pagination-offset","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}