{"record":{"id":"8d3c7daabf620620","repo":"dmtrKovalenko/fff","slug":"operation-aborted","errorCode":null,"errorMessage":"Operation aborted","messagePattern":"Operation aborted","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/pi-fff/src/index.ts","lineNumber":867,"sourceCode":"    ),\n    cursor: Type.Optional(\n      Type.String({ description: \"Pagination cursor from previous result\" }),\n    ),\n  });\n\n  queueTool(() => toolNames.grep, {\n    description: `Grep file contents. Smart-case, auto-detects regex vs literal, git-aware. Results are ranked by frecency (most-accessed files first); matches within a file stay in source order. Default limit ${DEFAULT_GREP_LIMIT}.`,\n    promptSnippet: \"Grep contents\",\n    promptGuidelines: (names) => [\n      `${names.grep}: prefer bare identifiers as patterns. Literal queries are most efficient.`,\n      `${names.grep}: use path for include ('src/', '*.ts') and exclude for noise ('test/,*.min.js').`,\n      `${names.grep}: caseSensitive: true when you need exact case (smart-case otherwise).`,\n      `${names.grep}: after 1-2 greps, read the top match instead of more greps.`,\n    ],\n    parameters: grepSchema,\n\n    async execute(_toolCallId, params, signal) {\n      if (signal?.aborted) throw new Error(\"Operation aborted\");\n\n      const pattern = params.pattern;\n      const aux = await resolveFinderForPath(params.path, pattern, params.exclude);\n\n      const picker = aux ? aux.finder : await ensureFinder(activeCwd);\n      const effectiveLimit = Math.max(1, params.limit ?? DEFAULT_GREP_LIMIT);\n      // pageSize caps TOTAL matches across all files (soft cap: the current file\n      // is always finished first). maxMatchesPerFile stays decoupled at the engine\n      // default so same-file overflow remains reachable via cursor (#825).\n      const pageSize = Math.min(effectiveLimit, GREP_PAGE_SIZE_MAX);\n      const context = clampContext(params.context);\n      const query = aux\n        ? aux.query\n        : buildQuery(params.path, pattern, params.exclude, activeCwd);\n\n      // Auto-detect: regex if the pattern has regex metacharacters AND parses\n      // as a valid regex, otherwise plain literal. The fuzzy fallback below\n      // only kicks in for plain mode — regex queries are intentional.","sourceCodeStart":849,"sourceCodeEnd":885,"githubUrl":"https://github.com/dmtrKovalenko/fff/blob/7f8537e70f0ea1210f9acbbfc4640141105cdc78/packages/pi-fff/src/index.ts#L849-L885","documentation":"The grep tool's execute function checks the caller-supplied AbortSignal at the start and throws if the request was already cancelled. This is an eager bail-out so no picker work is done for a cancelled request.","triggerScenarios":"The host (agent harness or user pressing Ctrl-C) aborts the signal before/while the grep tool handler starts; `signal.aborted` is true on entry.","commonSituations":"Agent run cancelled between planning and tool execution; slow UI causing the user to cancel a pending grep; timeouts in the calling framework aborting the signal.","solutions":["Treat this as normal cancellation — re-issue the grep in a new request if it is still needed","Don't reuse/forward an already-aborted AbortSignal to a new tool call; create a fresh controller per call","Check upstream timeout configuration if signals abort too early"],"exampleFix":"// before\ncontroller.abort();\nawait grepTool.execute(id, params, controller.signal);\n\n// after\nconst fresh = new AbortController();\nawait grepTool.execute(id, params, fresh.signal);","handlingStrategy":"retry","validationCode":"if (controller.signal.aborted) controller = new AbortController();","typeGuard":null,"tryCatchPattern":"try { await grepTool.execute(id, params, signal); } catch (e) { if (String(e).includes('aborted')) return null; throw e; }","preventionTips":["Create a fresh AbortController per tool call","Never forward already-aborted signals","Set realistic upstream timeouts so signals don't fire prematurely"],"tags":["abort","cancellation","async"],"backgroundTag":"operation-aborted","analyzedSha":"7f8537e70f0ea1210f9acbbfc4640141105cdc78","analyzedAt":"2026-09-10T07:26:53.407Z","contentChangedAt":"2026-09-10T07:26:53.407Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}