{"record":{"id":"0ff3a8034c44cd92","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-query-0ff3a8","errorCode":"error-invalid-query","errorMessage":"isValidQuery.errors.join('\\n')","messagePattern":"isValidQuery\\.errors\\.join\\('\\\\n'\\)","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/users.ts","lineNumber":707,"sourceCode":"\t\t\t// if user provided a query, validate it with their allowed operators\n\t\t\t// otherwise we use the default query (with $regex and $options)\n\t\t\tif (\n\t\t\t\t!isValidQuery(\n\t\t\t\t\tnonEmptyQuery,\n\t\t\t\t\t[\n\t\t\t\t\t\t...inclusiveFieldsKeys,\n\t\t\t\t\t\tinclusiveFieldsKeys.includes('emails') && 'emails.address.*',\n\t\t\t\t\t\tinclusiveFieldsKeys.includes('username') && 'username.*',\n\t\t\t\t\t\tinclusiveFieldsKeys.includes('name') && 'name.*',\n\t\t\t\t\t\tinclusiveFieldsKeys.includes('type') && 'type.*',\n\t\t\t\t\t\tinclusiveFieldsKeys.includes('customFields') && 'customFields.*',\n\t\t\t\t\t].filter(Boolean) as string[],\n\t\t\t\t\t// At this point, we have already validated the user query not containing malicious fields\n\t\t\t\t\t// On here we are using our own query so we can allow some extra fields\n\t\t\t\t\t[...this.queryOperations, '$regex', '$options'],\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-query', isValidQuery.errors.join('\\n'));\n\t\t\t}\n\n\t\t\tconst actualSort = sort || { username: 1 };\n\n\t\t\tif (sort?.status) {\n\t\t\t\tactualSort.active = sort.status;\n\t\t\t}\n\n\t\t\tif (sort?.name) {\n\t\t\t\tactualSort.nameInsensitive = sort.name;\n\t\t\t}\n\n\t\t\tconst limit =\n\t\t\t\tcount !== 0\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$limit: count,\n\t\t\t\t\t\t\t},","sourceCodeStart":689,"sourceCodeEnd":725,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/users.ts#L689-L725","documentation":"Thrown by the users.list query path when the sanitized query fails validateQuery (the ajv-based guard that restricts allowed fields/operators). The message is the joined ajv error list, so it tells you exactly which field/operator was rejected.","triggerScenarios":"GET users.list?query=... with a field or MongoDB operator not in the allowed allow-list, or with a syntactically invalid query JSON.","commonSituations":"Client builds a query with a field the server does not expose (e.g. arbitrary services.* keys); using $where or other banned operators; malformed JSON from a query builder.","solutions":["Read the joined error text returned - it names the offending field/operator; remove or replace it.","Restrict the query to the documented allowed fields and the allowed operator set ([queryOperations, $regex, $options]).","URL-encode and JSON-validate the query parameter before sending."],"exampleFix":"// before\nGET /api/v1/users.list?query={ \"services.google\": { $exists: true } }\n\n// after - query an allowed, indexed field\nGET /api/v1/users.list?query={ \"emails.address\": { $regex: \"@example.com\", $options: \"i\" } }","handlingStrategy":"validation","validationCode":"// Allow-list fields and operators before sending the query\nconst ALLOWED_FIELDS = ['username', 'emails.address', 'name', 'type', 'status', 'roles'];\nconst ALLOWED_OPS = ['$eq', '$ne', '$in', '$nin', '$regex', '$options', '$exists'];\nfunction sanitizeQuery(q: unknown): unknown {\n  // walk q, drop unknown keys/ops, return cleaned query or null\n}\nconst clean = sanitizeQuery(rawQuery);\nawait GET(`users.list?query=${encodeURIComponent(JSON.stringify(clean))}`);","typeGuard":"const isAllowedQuery = (q: any, allowed: string[]): boolean =>\n  q && typeof q === 'object' && Object.keys(q).every((k) => allowed.includes(k));","tryCatchPattern":"try {\n  await GET(`users.list?query=${encodeURIComponent(JSON.stringify(q))}`);\n} catch (e) {\n  if (isMeteorError(e, 'error-invalid-query')) {\n    // e.reason contains the ajv errors; use them to fix the query\n  } else { throw e; }\n}","preventionTips":["Build queries from a documented allow-list of fields/operators.","JSON-validate and URL-encode the query parameter.","Parse the returned ajv error text to guide the fix."],"tags":["users","query","validation","api","security"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}