rohitg00/agentmemory · error · Error
mem::search: query must be a non-empty string
Error message
mem::search: query must be a non-empty string
What it means
mem::search requires a query that is a string containing non-whitespace characters. The function normalizes by trimming and throws this validation error up front rather than running a search with an empty query, which would return meaningless results.
Source
Thrown at src/functions/search.ts:384
}
export function registerSearchFunction(sdk: ISdk, kv: StateKV): void {
sdk.registerFunction(
'mem::search',
async (data: {
query: string
limit?: number
project?: string
cwd?: string
format?: string
token_budget?: number
agentId?: string
}) => {
const idx = getSearchIndex()
// Input validation / normalization.
if (typeof data?.query !== 'string' || !data.query.trim()) {
throw new Error('mem::search: query must be a non-empty string')
}
const query = data.query.trim()
const MAX_LIMIT = 100
let effectiveLimit = 20
if (data.limit !== undefined) {
if (!Number.isInteger(data.limit) || data.limit < 1) {
throw new Error('mem::search: limit must be a positive integer')
}
effectiveLimit = Math.min(data.limit, MAX_LIMIT)
}
const projectFilter = typeof data.project === 'string' && data.project.trim().length > 0 ? data.project.trim() : undefined
const cwdFilter = typeof data.cwd === 'string' && data.cwd.trim().length > 0 ? data.cwd.trim() : undefined
// #817: agent-scope isolation. mem::search backs REST /search,
// memory_recall and recall_context. Without filtering here a
// worker booted with AGENT_ID=B + AGENTMEMORY_AGENT_SCOPE=isolated
// could read A's memories — the cross-agent leak the issue
// documented. Mirrors the smart-search pattern: wildcard "*"
// bypasses, explicit agentId pins, isolated mode falls back toView on GitHub (pinned to e04ba88819)
Solutions
- Ensure the payload includes query as a non-empty string.
- Guard on the caller side: if (!q?.trim()) skip the search call.
- Fix field-name mismatches so the value actually lands in data.query.
- Validate/sanitize user input from UIs before forwarding.
Example fix
// before
await trigger({ function_id: 'mem::search', payload: { query: input.q } });
// after
const q = (input.q ?? '').trim();
if (!q) return { results: [] };
await trigger({ function_id: 'mem::search', payload: { query: q } }); Defensive patterns
Strategy: validation
Validate before calling
const q = typeof input.query === 'string' ? input.query.trim() : '';
if (!q) throw new Error('search requires a non-empty query'); Type guard
function isNonEmptyString(v: unknown): v is string {
return typeof v === 'string' && v.trim().length > 0;
} Try / catch
try {
return await trigger({ function_id: 'mem::search', payload: { query } });
} catch (e) {
if (String(e.message).includes('query must be a non-empty string')) {
return { results: [] };
}
throw e;
} Prevention
- Trim and check length before every search call.
- Treat empty search boxes as no-op rather than forwarding them.
- Keep the payload field named exactly 'query'.
- Add contract tests asserting the search payload shape.
When it happens
Trigger: Calling mem::search (or REST /search / the MCP search tool) with query omitted, null, a number, an empty string '', or a whitespace-only string like ' '.
Common situations: MCP client sending missing/optional query parameter; UI sending the raw value of an empty search box; a refactor renaming the field (e.g. q vs query) so data.query is undefined.
Related errors
- mem::search: limit must be a positive integer
- mem::search: format must be one of 'full', 'compact', or 'na
- 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/30e7643e9a6fb9cb.
Report an issue: GitHub.