mastra-ai/mastra · error
Pin budget exceeded: the pin set is limited to ${options.max
Error message
Pin budget exceeded: the pin set is limited to ${options.maxCharacters} characters in total. What it means
Pins are injected wholesale into context, so their combined size is capped at options.maxCharacters. assertBudget sums the characters of the pins that would remain (excluding the replaced pin, if any) plus the incoming text and throws when the total would exceed the cap. Unlike the count limit, this check also applies to replacements if the replacement text is too large.
Source
Thrown at packages/memory/src/processors/observational-memory/subconscious/pinned.ts:118
return { nodeId, pins };
}
function totalCharacters(pins: KnowledgeRecord[]): number {
return pins.reduce((sum, pin) => sum + pin.text.length, 0);
}
function assertBudget(
options: PinnedToolsOptions,
pins: KnowledgeRecord[],
incomingText: string,
replacing?: KnowledgeRecord,
): void {
const kept = replacing ? pins.filter(pin => pin.id !== replacing.id) : pins;
if (!replacing && kept.length >= options.maxPins) {
throw new Error(`Pin limit reached: the set holds at most ${options.maxPins}. Unpin something first.`);
}
if (totalCharacters(kept) + incomingText.length > options.maxCharacters) {
throw new Error(`Pin budget exceeded: the pin set is limited to ${options.maxCharacters} characters in total.`);
}
}
// Pins cannot be written broader than the resource level: the reserved node
// is anchored at (or below) the resource, and an org-scoped pin would only be
// resolvable from the resource that created it, which is a silent-loss trap.
function clampPinLevel(level: KnowledgeScopeLevel): KnowledgeScopeLevel {
return level === 'org' ? 'resource' : level;
}
function resolveWriteScope(options: PinnedToolsOptions, level?: KnowledgeScopeLevel): KnowledgeScope {
// An unscoped pin under a thread ceiling narrows to the ceiling instead of
// failing the assert on every call: pins are model-driven, so a config that
// makes the default request throw would be a tool error every turn.
let effective = clampPinLevel(level ?? options.defaultScope);
if (!level && options.maxScope === 'thread') effective = 'thread';
const scope = expandKnowledgeScope(options.scope, effective);
assertKnowledgeScopeWithinCeiling(scope, options.maxScope);View on GitHub (pinned to 75dd419e61)
Solutions
- Shorten/summarize the text before pinning
- Unpin or replace verbose pins with tighter versions to free character budget
- Raise options.maxCharacters in the pinned tools configuration
- Enforce a client-side length check on pin text before calling the tool
Example fix
// before: pinning a 5000-char summary against a 4000-char budget
await pinTool.execute({ text: longSummary });
// Error: Pin budget exceeded: the pin set is limited to 4000 characters in total.
// after
const trimmed = summarize(longSummary, 800);
await pinTool.execute({ text: trimmed }); Defensive patterns
Strategy: validation
Validate before calling
const pins = await listPins(memory);
const total = pins.reduce((n, p) => n + p.text.length, 0);
if (total + text.length > maxCharacters) {
throw new Error(`Pinning ${text.length} chars would exceed the ${maxCharacters}-character pin budget.`);
} Type guard
function fitsCharacterBudget(pins, incoming, maxCharacters) {
const total = pins.reduce((n, p) => n + p.text.length, 0);
return total + incoming.length <= maxCharacters;
} Try / catch
try {
await pinTool.execute({ text });
} catch (err) {
if (err.message.startsWith('Pin budget exceeded')) {
// shorten the text or free budget by unpinning/replacing verbose pins
} else throw err;
} Prevention
- Summarize before pinning; pins should be terse
- Check cumulative character usage when maxCharacters changes
- Prune near-duplicate pins regularly
- Reserve headroom (e.g. cap client-side at 80% of maxCharacters)
When it happens
Trigger: Pinning text whose length pushes totalCharacters(kept) + incomingText.length past maxCharacters — including oversized replacements.
Common situations: Pasting long documents or verbose summaries as pins; maxCharacters reduced in config below the existing pins' total size; repeated pinning of near-duplicate content that silently accumulates characters.
Related errors
- Pin limit reached: the set holds at most ${options.maxPins}.
- Knowledge node is not a skill: ${normalizedName}
- Pin not found: ${recordId}
- Record is not a pin: ${recordId}
- AGENT_NETWORK_OBSERVATIONAL_MEMORY_UNSUPPORTED
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/a73550b56a5e9197.
Report an issue: GitHub.