mastra-ai/mastra · error · TripWire
TokenLimiterProcessor: No messages fit within the remaining
Error message
TokenLimiterProcessor: No messages fit within the remaining token budget. Cannot send LLM a request with no messages.
What it means
After keeping all system messages, TokenLimiterProcessor runs best-fit selection over non-system messages against the remaining budget (remainingBudget = limit - systemTokens - conversation overhead). If not even one non-system message fits, the resulting request would contain no conversational messages, so the processor throws a TripWire with retry:false.
Source
Thrown at packages/core/src/processors/processors/token-limiter.ts:206
for (let i = messages.length - 1; i >= 0; i--) {
const message = messages[i];
if (!message) continue;
const messageTokens = await this.countInputMessageTokens(message);
if (currentTokens + messageTokens <= remainingBudget) {
messagesToKeep.unshift(message);
currentTokens += messageTokens;
} else {
if (this.trimMode === 'contiguous') {
break;
}
// best-fit → continue (existing behavior)
}
}
if (messagesToKeep.length === 0) {
throw new TripWire(
'TokenLimiterProcessor: No messages fit within the remaining token budget. Cannot send LLM a request with no messages.',
{
retry: false,
metadata: { systemTokens, limit, remainingBudget, messageCount: messages.length },
},
);
}
// Remove messages that don't fit within the token budget
const keepIds = new Set(messagesToKeep.map(m => m.id));
const idsToRemove = messages.filter(m => !keepIds.has(m.id)).map(m => m.id);
if (idsToRemove.length > 0) {
messageList.removeByIds(idsToRemove);
}
}
/**
* Count tokens for a system message. Accepts both untagged and tagged system messagesView on GitHub (pinned to 75dd419e61)
Solutions
- Raise maxTokens so the remaining budget after system messages fits at least the latest user message.
- Split or truncate very large user messages before they reach the processor.
- Reduce system prompt size to increase remainingBudget.
- Catch the TripWire and implement application-level truncation/chunking of the input before retrying.
Example fix
// before
new TokenLimiterProcessor({ maxTokens: 2000 }); // remainingBudget < any single message
// after
new TokenLimiterProcessor({ maxTokens: 16000 }); Defensive patterns
Strategy: validation
Validate before calling
const largestMsgTokens = Math.max(...nonSystemMessages.map(m => processor.countTokens(String(m.content))));
const remainingBudget = maxTokens - systemTokens - 1000;
if (remainingBudget < largestMsgTokens) {
throw new Error('Remaining token budget cannot fit any single message; raise maxTokens or truncate input');
} Try / catch
try {
await agent.generate(input);
} catch (e) {
if (e?.name === 'TripWire' && e?.message?.includes('No messages fit')) {
// truncate/chunk the newest user message, then retry once
} else throw e;
} Prevention
- Cap individual user message sizes at ingestion time.
- Reserve headroom: maxTokens >= systemTokens + largestExpectedMessage + overhead.
- Chunk large documents before sending them to the agent.
When it happens
Trigger: processInputStep: messagesToKeep.length === 0 after best-fit selection because remainingBudget is smaller than the token count of every candidate message (metadata includes systemTokens, limit, remainingBudget, messageCount).
Common situations: A maxTokens barely above the system prompt size; one enormous user message (e.g. a pasted document) that alone exceeds the budget; a long conversation where the newest message alone doesn't fit.
Related errors
- TokenLimiterProcessor: System messages alone exceed token li
- Aborted by processor
- countCoreSystemMessageTokens can only be used with system me
- countCoreSystemMessageTokens: System message content must be
- Tripwire triggered by ${processor.id}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/a5fb60dac5765767.
Report an issue: GitHub.