{"record":{"id":"7ad16d1d9af6a478","repo":"mastra-ai/mastra","slug":"tokenlimiterprocessor-no-messages-to-process-can","errorCode":null,"errorMessage":"TokenLimiterProcessor: No messages to process. Cannot send LLM a request with no messages.","messagePattern":"TokenLimiterProcessor: No messages to process\\. Cannot send LLM a request with no messages\\.","errorType":"exception","errorClass":"TripWire","httpStatus":null,"severity":"error","filePath":"packages/core/src/processors/processors/token-limiter.ts","lineNumber":156,"sourceCode":"\n  /**\n   * Process input messages at each step of the agentic loop, before they are sent to the LLM.\n   * Runs at every step (including tool call continuations), preventing the conversation history\n   * from growing unboundedly during multi-step agent workflows.\n   *\n   * System messages are always preserved, and the most recent non-system messages are kept\n   * within the token budget.\n   */\n  async processInputStep(args: ProcessInputStepArgs): Promise<void> {\n    const { messageList } = args;\n\n    if (!messageList) return;\n\n    const messages = messageList.get.all.db();\n\n    // If no messages or empty array, throw TripWire - can't send LLM a request with no messages\n    if (!messages || messages.length === 0) {\n      throw new TripWire('TokenLimiterProcessor: No messages to process. Cannot send LLM a request with no messages.', {\n        retry: false,\n      });\n    }\n\n    // Budget against the full system message set that will reach the model\n    // (untagged + tagged buckets), not just the untagged view exposed via args.\n    const allSystemMessages = messageList.getAllSystemMessages();\n    let systemTokens = 0;\n    for (const msg of allSystemMessages) {\n      systemTokens += await this.countCoreSystemMessageTokens(msg);\n    }\n\n    const limit = this.maxTokens;\n\n    // If system messages alone exceed the token limit (accounting for conversation overhead),\n    // throw TripWire - can't send LLM a request with only system messages\n    if (systemTokens + TokenLimiterProcessor.TOKENS_PER_CONVERSATION >= limit) {\n      throw new TripWire(","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/processors/processors/token-limiter.ts#L138-L174","documentation":"TokenLimiterProcessor's `processInputStep` fetches all messages from the incoming MessageList and throws a TripWire (with `retry: false`) when there is nothing to process — an LLM request with zero messages is invalid. This guards against sending doomed requests downstream; the TripWire aborts the step rather than silently passing an empty list.","triggerScenarios":"Calling an agent/generation step whose MessageList is empty: no user/system messages were added before the processor ran, all prior processors stripped every message, or a workflow step invokes the pipeline with an empty `messages: []` array.","commonSituations":"Building message lists dynamically where a filter removed all messages, empty user input passed straight through, memory/storage returning no messages for a fresh thread while the caller sends nothing new, and tests that construct agents without seed messages.","solutions":["Ensure at least one user (or system) message exists before invoking the pipeline.","Guard your caller: skip generation when `messages.length === 0` and return early instead.","Check whether an upstream processor (filter/redactor) is stripping all messages and adjust its rules.","Since `retry: false`, do not retry as-is — fix the input, or catch the TripWire and return a friendly 'no input' response."],"exampleFix":"// before\nawait agent.generate(userInput?.trim() ?? '');\n// after\nif (!userInput?.trim()) return 'No input provided';\nawait agent.generate(userInput);","handlingStrategy":"try-catch","validationCode":"const msgs = messageList.get.all.db();\nif (!msgs || msgs.length === 0) {\n  // skip generation entirely instead of running the pipeline\n  return null;\n}","typeGuard":"function hasMessages(list: MessageList | undefined): list is MessageList {\n  return Boolean(list && list.get.all.db().length > 0);\n}","tryCatchPattern":"try {\n  result = await agent.generate(input);\n} catch (e) {\n  if (e instanceof TripWire && e.message.includes('No messages to process')) {\n    result = { text: 'No input provided.' }; // retry: false, so don't retry\n  } else throw e;\n}","preventionTips":["Guard callers: never invoke generation with empty/whitespace-only input.","Audit upstream processors for rules that could strip all messages.","Ensure fresh threads still send at least a system or user message.","Catch TripWire with retry:false at the edge and convert to a user-friendly response."],"tags":["tripwire","messages","runtime","token-limiter"],"backgroundTag":"empty-message-list","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}