rohitg00/agentmemory · error · Error

mem::search: format must be one of 'full', 'compact', or 'na

Error message

mem::search: format must be one of 'full', 'compact', or 'narrative'

What it means

mem::search supports an optional format parameter controlling output shape; it defaults to 'full' and must be one of 'full', 'compact', or 'narrative'. Any other string is rejected before the search executes.

Source

Thrown at src/functions/search.ts:435

      const filterAgentId = wildcardAgent
        ? undefined
        : explicitAgentId ?? envAgentId;
      if (
        isolated &&
        !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
            })

View on GitHub (pinned to e04ba88819)

Solutions

  1. Use exactly one of 'full', 'compact', or 'narrative' (lowercase).
  2. Omit format to get the 'full' default.
  3. Whitelist the value on the caller side before forwarding user-selected options.
  4. Fix case mismatches by lowercasing input first.

Example fix

// before
await trigger({ function_id: 'mem::search', payload: { query: q, format: opts.mode } });
// after
const FORMATS = ['full', 'compact', 'narrative'];
const format = FORMATS.includes(opts.mode) ? opts.mode : undefined;
await trigger({ function_id: 'mem::search', payload: { query: q, format } });
Defensive patterns

Strategy: type-guard

Validate before calling

const FORMATS = ['full', 'compact', 'narrative'] as const;
type SearchFormat = typeof FORMATS[number];
function toFormat(v: unknown): SearchFormat | undefined {
  return typeof v === 'string' && (FORMATS as readonly string[]).includes(v) ? v as SearchFormat : undefined;
}

Type guard

function isSearchFormat(v: unknown): v is 'full' | 'compact' | 'narrative' {
  return v === 'full' || v === 'compact' || v === 'narrative';
}

Try / catch

try {
  return await trigger({ function_id: 'mem::search', payload: { query, format } });
} catch (e) {
  if (String(e.message).includes("format must be one of")) {
    return await trigger({ function_id: 'mem::search', payload: { query } });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling mem::search with format set to an unsupported value such as 'text', 'json', 'verbose', 'summary', or a typo like 'narative'.

Common situations: Clients written against an older/newer API surface with different format names; free-form UI dropdown values forwarded directly; case-sensitivity mistakes ('Full').

Related errors


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