rohitg00/agentmemory · error · Error
mem::search: token_budget must be a positive integer
Error message
mem::search: token_budget must be a positive integer
What it means
The mem::search function validates every argument at the system boundary. token_budget is an optional input that caps the token cost of the formatted search result; if supplied it must be an integer >= 1 (Number.isInteger check plus < 1 rejection). Passing a float, 0, a negative number, or a non-number type makes the function throw immediately rather than silently mis-budgeting the response.
Source
Thrown at src/functions/search.ts:440
!wildcardAgent &&
!explicitAgentId &&
!envAgentId
) {
throw new Error(
"mem::search: AGENTMEMORY_AGENT_SCOPE=isolated is set but no " +
"agent id is available (env AGENT_ID unset and no explicit " +
"agentId in the call). Refusing to read cross-agent rows. " +
'Pass agentId: "*" to opt in to a wildcard read.',
);
}
const format = typeof data.format === 'string' ? data.format : 'full'
if (!['full', 'compact', 'narrative'].includes(format)) {
throw new Error("mem::search: format must be one of 'full', 'compact', or 'narrative'")
}
let tokenBudget: number | undefined
if (data.token_budget !== undefined) {
if (!Number.isInteger(data.token_budget) || data.token_budget < 1) {
throw new Error('mem::search: token_budget must be a positive integer')
}
tokenBudget = data.token_budget
}
if (idx.size === 0) {
// Share one rebuild across concurrent cold-start queries so they
// don't each walk the whole corpus and saturate the pool.
if (!rebuildPromise) {
rebuildPromise = rebuildIndex(kv)
.then((count) => {
logger.info('Search index rebuilt', { entries: count })
return count
})
.catch((err) => {
logger.warn('Index rebuild failed', {
error: err instanceof Error ? err.message : String(err),
})
return 0View on GitHub (pinned to e04ba88819)
Solutions
- Pass token_budget as a whole number >= 1, or omit the field entirely to use the default budget.
- Coerce string inputs with Number(value) and round with Math.round/Math.floor before the call.
- Treat 0 or negative values as 'unset' by deleting the property instead of sending it.
Example fix
// before
await sdk.trigger({ function_id: "mem::search", payload: { query, token_budget: req.query.budget } });
// after
const raw = req.query.budget;
const token_budget = raw ? Math.max(1, Math.round(Number(raw))) : undefined;
await sdk.trigger({ function_id: "mem::search", payload: { query, ...(token_budget !== undefined ? { token_budget } : {}) } }); Defensive patterns
Strategy: validation
Validate before calling
function validTokenBudget(v) {
return v === undefined || (Number.isInteger(v) && v >= 1);
}
// call only if validTokenBudget(payload.token_budget) Type guard
function isTokenBudget(v: unknown): v is number {
return typeof v === "number" && Number.isInteger(v) && v >= 1;
} Try / catch
try {
result = await sdk.trigger({ function_id: "mem::search", payload });
} catch (e) {
if (String(e.message).includes("token_budget must be a positive integer")) {
delete payload.token_budget; // retry with default budget
result = await sdk.trigger({ function_id: "mem::search", payload });
} else throw e;
} Prevention
- Never send token_budget: 0 as a sentinel for 'unset' — delete the key instead.
- Coerce and round user/config input with Math.round(Number(x)) before passing.
- Whitelist tool-call args from LLMs and validate numeric fields before triggering.
When it happens
Trigger: Calling sdk.trigger({ function_id: 'mem::search', payload: { query, token_budget: X } }) where X is 0, negative, a non-integer (e.g. 512.5), a numeric string like "512", null (as an explicit value is still defined), or any non-number type.
Common situations: Parsing the budget from a config file or CLI flag without Number() coercion, LLM-generated tool-call arguments arriving as strings, dividing a budget across calls producing fractions, or a client defaulting the field to 0 meaning 'unset'.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- content is required
- query is required
- Unknown tool: ${toolName}
- memoryIds is required
- Invalid dateFrom: ${filter.dateFrom}
AI-assisted analysis of rohitg00/agentmemory@e04ba88819 (2026-08-30).
Data as JSON: /api/errors/f08d244da9d47c69.
Report an issue: GitHub.