Skip to content

Cline exhausts context window on src/core/task/index.ts (≈4 000 LOC) #3095

Closed as not planned

Description

@JanNoszczyk

What happened?

When I open src/core/task/index.ts and ask Cline to do a minor code refactor (it works with simple changes) the extension returns “context-window overflow” and aborts.
The file is roughly four thousand lines, and Cline is configured with a 1 M-token limit, so this should not happen with typical usage.

Actual Behavior

  • Extension logs show a context-overflow error.
  • No response is produced; the agent stops.

Expected Behavior

Cline should load the file—or at least stream it in workable slices—without exceeding the available context window, just as it does for the rest of the codebase.


Suspected Root Cause

src/core/task/index.ts is a single monolithic file.
Because the entire file is sent to the model every time, Cline cannot stay within its token budget.

Also, replace_in_files seems to be doing some grep line by line on the file and I think that's the reason it hangs. Towards the end of the file, you can see Cline visibly slowing down, taking much longer to scan a single line


Proposed Fixes

Break index.ts into 3–4 focused modules and re-export from index.ts to avoid a breaking change:

New file Responsibility
task-definitions.ts Shared types, interfaces, enums, constants, and simple helpers (mapStringToPlatformEnum, formatErrorWithStatusCode, …)
task-io.ts All input/output operations: webview communication (ask/say), gRPC interactions (postInitialStateToGrpcClient), state persistence (history saving, saveClineMessagesAndUpdateHistory), checkpoint management (restoreCheckpoint, saveCheckpoint, CheckpointTracker)
task-tool-handler.ts Parsing and handling assistant messages (presentAssistantMessage), tool-execution logic (executeCommandTool, browser actions, use_mcp_tool/access_mcp_resource), auto-approval helpers (shouldAutoApproveTool*), context loading (loadContext)
task-lifecycle.ts (optional) Core task orchestration: Task constructor, startTask, resumeTaskFromHistory, main agent loop (initiateTaskLoop, recursivelyMakeClineRequests), API-interaction logic (attemptApiRequest), task abortion flow (abortTask)

Splitting the logic makes the code a lot more readable, editable, not to mention the merge conflicts. But most importantly it would allow working on it with Cline and fixing our context overflow issue. On my fork of Cline i found myself making changes to it myself frequently, so I split it up into 2 big files (not 4 like proposed), this helped a little, but 2 files ended up being almost 2k LOC each....

Together with this refactor we would also be addressing the main issue of context overflow which also occurs inside task index.ts.


Steps to reproduce

  1. Open src/core/task/index.ts (≈4 000 lines) in VS Code.
  2. Ask Cline to perform any analysis (e.g. “summarize this file” or “find where executeTask is defined”).
  3. Observe the extension output / dev-tools console.

Relevant Logs (trimmed)

// …excerpt showing first overflow message …
ClineError: context_window_overflow (needed: 4 286 KB, available: 1 024 KB)
    at presentAssistantMessage (task/index.ts:2 977:13)
// …additional stack frames…





### Relevant API REQUEST output

> ```shell
<<<<<<< SEARCH
				// Assign correct oneof payload based on internal type
				if (msg.type === "ask" && msg.ask) {
					protoMsg.ask_type = msg.ask; // Map internal ask string to proto enum (assuming direct mapping)
					// Add specific payload assignments here if needed based on msg.ask value
				} else if (msg.type === "say" && msg.say) {
					protoMsg.say_type = msg.say; // Map internal say string to proto enum (assuming direct mapping)
					// Add specific payload assignments here if needed based on msg.say value
					// Example for SAY_API_REQ_INFO:
					// if (msg.say === "api_req_started" || msg.say === "api_req_finished" || msg.say === "api_req_retried") {
=======
				// Assign correct oneof payload based on internal type
				if (msg.type === "ask" && msg.ask) {
					// Map internal ask string to proto enum (assuming direct mapping - requires enum keys match string values)
					const askTypeEnumKey = msg.ask.toUpperCase() as keyof typeof ClineAskType;
					protoMsg.ask_type = ClineAskType[askTypeEnumKey] || ClineAskType.CLINE_ASK_TYPE_UNSPECIFIED;
					// Add specific payload assignments here if needed based on msg.ask value
				} else if (msg.type === "say" && msg.say) {
					// Map internal say string to proto enum (assuming direct mapping - requires enum keys match string values)
					const sayTypeEnumKey = msg.say.toUpperCase() as keyof typeof ClineSayType;
					protoMsg.say_type = ClineSayType[sayTypeEnumKey] || ClineSayType.CLINE_SAY_TYPE_UNSPECIFIED;
					// Add specific payload assignments here if needed based on msg.say value
					// Example for SAY_API_REQ_INFO:
					// if (msg.say === "api_req_started" || msg.say === "api_req_finished" || msg.say === "api_req_retried") {
>>>>>>> REPLACE

<<<<<<< SEARCH
					tokens_in: item.tokensIn,
					tokens_out: item.tokensOut,
					cache_writes: item.cacheWrites,
					cache_reads: item.cacheReads,
					total_cost: item.totalCost,
					size: item.size,
					shadow_git_config_work_tree: item.shadowGitConfigWorkTree,
					conversation_history_deleted_range: item.conversationHistoryDeletedRange
						? { start_index: item.conversationHistoryDeletedRange.start, end_index: item.conversationHistoryDeletedRange.end } // Map to proto structure
						: undefined,
				};
				return historyItemProto;
			});

			// Construct the STATE message payload conforming to ExtensionState proto definition
			const statePayload: ExtensionState = { // Construct the payload object first
				api_configuration: allState.apiConfiguration, // Ensure snake_case matches proto
				auto_approval_settings: allState.autoApprovalSettings, // Ensure snake_case matches proto
				browser_settings: allState.browserSettings, // Ensure snake_case matches proto
				// remote_browser_host: allState.remoteBrowserHost, // Check if this exists in allState and proto
				chat_settings: allState.chatSettings, // Ensure snake_case matches proto
				checkpoint_tracker_error_message: this.checkpointTrackerErrorMessage, // Ensure snake_case matches proto
				cline_messages: protoClineMessages, // Use correctly mapped proto type
				current_task_item: protoTaskHistory.find((item) => item.id === this.taskId), // Ensure snake_case matches proto
				custom_instructions: allState.customInstructions, // Ensure snake_case matches proto
				mcp_marketplace_enabled: allState.mcpMarketplaceEnabled, // Ensure snake_case matches proto
				plan_act_separate_models_setting: allState.planActSeparateModelsSetting, // Ensure snake_case matches proto
=======
					// Use snake_case names directly as expected by the proto definition
					tokens_in: item.tokensIn || 0,
					tokens_out: item.tokensOut || 0,
					cache_writes: item.cacheWrites, // Keep optional
					cache_reads: item.cacheReads,   // Keep optional
					total_cost: item.totalCost || 0, // Ensure number/double
					size: item.size,               // Keep optional
					shadow_git_config_work_tree: item.shadowGitConfigWorkTree, // Keep optional
					conversation_history_deleted_range: item.conversationHistoryDeletedRange // Keep internal object format
						? { start_index: item.conversationHistoryDeletedRange.start, end_index: item.conversationHistoryDeletedRange.end }
						: undefined,
				};
				return historyItemProto;
			});

			// Construct the STATE message payload conforming to ExtensionState proto definition (using snake_case)
			const statePayload: ExtensionState = { // Construct the payload object first
				api_configuration: allState.apiConfiguration,
				auto_approval_settings: allState.autoApprovalSettings,
				browser_settings: allState.browserSettings,
				// remote_browser_host: allState.remoteBrowserHost, // Check if this exists
				chat_settings: allState.chatSettings,
				checkpoint_tracker_error_message: this.checkpointTrackerErrorMessage,
				cline_messages: protoClineMessages, // Use correctly mapped proto type
				current_task_item: protoTaskHistory.find((item) => item.id === this.taskId),
				custom_instructions: allState.customInstructions,
				mcp_marketplace_enabled: allState.mcpMarketplaceEnabled,
				plan_act_separate_models_setting: allState.planActSeparateModelsSetting,
>>>>>>> REPLACE

<<<<<<< SEARCH
				// Map internal ask/say strings to correct proto enums
				ask_type: lastMessage.ask ? ClineAskType[lastMessage.ask as keyof typeof ClineAskType] : undefined,
				say_type: lastMessage.say ? ClineSayType[lastMessage.say as keyof typeof ClineSayType] : undefined,
				text: lastMessage.text,
				images: lastMessage.images || [], // Ensure array
				partial: lastMessage.partial || false, // Ensure boolean
				conversationHistoryIndex: lastMessage.conversationHistoryIndex || 0, // Ensure number
				conversationHistoryDeletedRange: lastMessage.conversationHistoryDeletedRange, // Assumed object format
				lastCheckpointHash: lastMessage.lastCheckpointHash,
				isCheckpointCheckedOut: lastMessage.isCheckpointCheckedOut || false, // Ensure boolean
			}
			// Construct the PARTIAL_MESSAGE ExtensionMessage correctly
			const partialExtensionMessage: ExtensionMessage = {
				type: ExtensionMessageType.PARTIAL_MESSAGE,
				partialMessage:

Diff Edit Mismatch
The model used search patterns that don't match anything in the file. Retrying...

Provider/Model

gemini-2.5-pro-exp-03-25

Operating System

macOS Sequoia 15.3.2 (24D81)

Cline Version

3.13.1

Additional context

It would be great to get this fixed. Ive been trying to build something on my fork of cline, but navigating the task index.ts file with an AI agent ie. Cline is really difficult and always exhausts the context

Happy to submit a PR if maintainers agree with this direction.
Feel free to suggest an alternative structure or naming convention.

Thanks for the great project! ❤️

Activity

  1. changed the title [-]`src/core/task/index.ts` exhausts Cline’s context window (≈4 000 LOC)[/-] [+]Cline exhausts context window on `src/core/task/index.ts` (≈4 000 LOC)[/+] on Apr 24, 2025
  2. kevinneung commented on Apr 24, 2025

    @kevinneung
    Contributor

    "Hi @JanNoszczyk , thank you for logging this issue! I'll assign a team member shortly that can review your suggestions, get it prioritized, and collaborate.

    I want to mention: we really appreciate the attention to detail in your proposal, it's ripe for the collaboration we want to do at Cline with our community. Keep them coming!"

  3. pashpashpash commented on Apr 24, 2025

    @pashpashpash
    Contributor

    I'm unable to reproduce this issue, refer to the screenshot here:

    Image

    I @ mention the task/index.ts file and it works great, even with a 200k context window model. Maybe you could provide what specific models/providers you tried this with where it breaks?

    As goes for your refactoring suggestions, I totally agree. We're currently working towards refactoring a lot of this code and breaking it up.

  4. JanNoszczyk commented on Apr 26, 2025

    @JanNoszczyk
    Author

    Actually you need to ask it something more elaborate, it tends to work with easy changes using replace_in_file. Try asking it to do some random minor refactor inside the task index.ts file.
    I updated the issue description a little, I hope its clearer now.

  5. github-actions commented on Jun 28, 2025

    @github-actions
    Contributor

    This issue is stale because it has been open for 60 days with no activity.

  6. github-actions commented on Sep 22, 2025

    @github-actions
    Contributor

    This issue was closed because it has been inactive for 14 days since being marked as stale.

  7. gvelesandro commented on Mar 13, 2026

    @gvelesandro

    Hi @JanNoszczyk, I run Agents Need Context and I am researching one specific failure mode: the model can edit code, but loses usable repo or file context once a task stops being trivial. Your task/index.ts report is one of the clearer public examples of a large-file context limit turning a minor refactor into a dead end.

    If you are open to it, I would value one short written postmortem here: https://www.agentsneedcontext.com/agent-failure-postmortem

    I am looking for five specifics: what the agent was trying to do, what context was missing, where that context lived, what workaround you used, and what it cost. No pitch, just research.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

staleAuto-applied to inactive issues

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions