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 0

View on GitHub (pinned to e04ba88819)

Solutions

  1. Pass token_budget as a whole number >= 1, or omit the field entirely to use the default budget.
  2. Coerce string inputs with Number(value) and round with Math.round/Math.floor before the call.
  3. 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

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


AI-assisted analysis of rohitg00/agentmemory@e04ba88819 (2026-08-30). Data as JSON: /api/errors/f08d244da9d47c69. Report an issue: GitHub.