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
- Use exactly one of 'full', 'compact', or 'narrative' (lowercase).
- Omit format to get the 'full' default.
- Whitelist the value on the caller side before forwarding user-selected options.
- 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
- Use a const-asserted union type for format values in client code.
- Lowercase/trim user-selected formats before forwarding.
- Omit format when the default ('full') is acceptable.
- Keep client enum lists in sync with server releases.
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
- mem::search: query must be a non-empty string
- mem::search: limit must be a positive integer
- Invalid dateFrom: ${filter.dateFrom}
- Invalid dateTo: ${filter.dateTo}
- Refusing to read image outside managed store: ${data.raw.ima
AI-assisted analysis of rohitg00/agentmemory@e04ba88819 (2026-08-30).
Data as JSON: /api/errors/85a6e4360e06c956.
Report an issue: GitHub.