{"record":{"id":"30e7643e9a6fb9cb","repo":"rohitg00/agentmemory","slug":"mem-search-query-must-be-a-non-empty-string","errorCode":null,"errorMessage":"mem::search: query must be a non-empty string","messagePattern":"mem::search: query must be a non-empty string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/functions/search.ts","lineNumber":384,"sourceCode":"}\n\nexport function registerSearchFunction(sdk: ISdk, kv: StateKV): void {\n  sdk.registerFunction(\n    'mem::search',\n    async (data: {\n      query: string\n      limit?: number\n      project?: string\n      cwd?: string\n      format?: string\n      token_budget?: number\n      agentId?: string\n    }) => {\n      const idx = getSearchIndex()\n\n      // Input validation / normalization.\n      if (typeof data?.query !== 'string' || !data.query.trim()) {\n        throw new Error('mem::search: query must be a non-empty string')\n      }\n      const query = data.query.trim()\n      const MAX_LIMIT = 100\n      let effectiveLimit = 20\n      if (data.limit !== undefined) {\n        if (!Number.isInteger(data.limit) || data.limit < 1) {\n          throw new Error('mem::search: limit must be a positive integer')\n        }\n        effectiveLimit = Math.min(data.limit, MAX_LIMIT)\n      }\n      const projectFilter = typeof data.project === 'string' && data.project.trim().length > 0 ? data.project.trim() : undefined\n      const cwdFilter = typeof data.cwd === 'string' && data.cwd.trim().length > 0 ? data.cwd.trim() : undefined\n      // #817: agent-scope isolation. mem::search backs REST /search,\n      // memory_recall and recall_context. Without filtering here a\n      // worker booted with AGENT_ID=B + AGENTMEMORY_AGENT_SCOPE=isolated\n      // could read A's memories — the cross-agent leak the issue\n      // documented. Mirrors the smart-search pattern: wildcard \"*\"\n      // bypasses, explicit agentId pins, isolated mode falls back to","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/rohitg00/agentmemory/blob/e04ba88819c365c9acf9d6661ea802143e728bd6/src/functions/search.ts#L366-L402","documentation":"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.","triggerScenarios":"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 '   '.","commonSituations":"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.","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."],"exampleFix":"// before\nawait trigger({ function_id: 'mem::search', payload: { query: input.q } });\n// after\nconst q = (input.q ?? '').trim();\nif (!q) return { results: [] };\nawait trigger({ function_id: 'mem::search', payload: { query: q } });","handlingStrategy":"validation","validationCode":"const q = typeof input.query === 'string' ? input.query.trim() : '';\nif (!q) throw new Error('search requires a non-empty query');","typeGuard":"function isNonEmptyString(v: unknown): v is string {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  return await trigger({ function_id: 'mem::search', payload: { query } });\n} catch (e) {\n  if (String(e.message).includes('query must be a non-empty string')) {\n    return { results: [] };\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["validation","search","input-validation"],"backgroundTag":"invalid-search-query","analyzedSha":"e04ba88819c365c9acf9d6661ea802143e728bd6","analyzedAt":"2026-08-30T01:07:40.754Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}