{"record":{"id":"1a847ab017188de6","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-params","errorCode":"error-invalid-params","errorMessage":"error-invalid-params","messagePattern":"error-invalid-params","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/omnichannel/contact.ts","lineNumber":94,"sourceCode":"\t},\n\t{\n\t\tasync get() {\n\t\t\tcheck(this.queryParams, {\n\t\t\t\temail: Match.Maybe(String),\n\t\t\t\tphone: Match.Maybe(String),\n\t\t\t\tcustom: Match.Maybe(String),\n\t\t\t});\n\t\t\tconst { email, phone, custom } = this.queryParams;\n\n\t\t\tlet customCF: { [k: string]: string } = {};\n\t\t\ttry {\n\t\t\t\tcustomCF = custom && JSON.parse(custom);\n\t\t\t} catch (e) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-params-custom');\n\t\t\t}\n\n\t\t\tif (!email && !phone && !Object.keys(customCF).length) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-params');\n\t\t\t}\n\n\t\t\tconst foundCF = await (async () => {\n\t\t\t\tif (!custom) {\n\t\t\t\t\treturn {};\n\t\t\t\t}\n\n\t\t\t\tconst cfIds = Object.keys(customCF);\n\n\t\t\t\tconst customFields = await LivechatCustomField.findMatchingCustomFieldsByIds(cfIds, 'visitor', true, {\n\t\t\t\t\tprojection: { _id: 1 },\n\t\t\t\t}).toArray();\n\n\t\t\t\treturn Object.fromEntries(customFields.map(({ _id }) => [`livechatData.${_id}`, new RegExp(escapeRegExp(customCF[_id]), 'i')]));\n\t\t\t})();\n\n\t\t\tconst contact = await LivechatVisitors.findOneByEmailAndPhoneAndCustomField(email, phone, foundCF);\n\t\t\treturn API.v1.success({ contact });","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/omnichannel/contact.ts#L76-L112","documentation":"Thrown by GET /api/v1/omnichannel/contact.search when none of email, phone, or parsed custom fields are provided. The endpoint requires at least one search criterion — an empty search is rejected before querying the database.","triggerScenarios":"Calling contact.search with no query parameters at all, or with all parameters empty/null/whitespace. The check is: if (!email && !phone && !Object.keys(customCF).length).","commonSituations":"Client sends a bare request without any filter; all search fields were left blank in the UI form; the query string was stripped by a proxy or middleware.","solutions":["Provide at least one of email, phone, or custom as a non-empty query parameter.","Validate on the client side that at least one search criterion is present before making the request."],"exampleFix":"// before: no search criteria\nGET /api/v1/omnichannel/contact.search\n// after: at least one criterion\nGET /api/v1/omnichannel/contact.search?email=guest@example.com","handlingStrategy":"validation","validationCode":"// Ensure at least one search criterion is present before calling the API\nfunction validateContactSearchParams({ email, phone, custom }) {\n  const hasEmail = email && email.trim().length > 0;\n  const hasPhone = phone && phone.trim().length > 0;\n  const hasCustom = custom && Object.keys(typeof custom === 'string' ? JSON.parse(custom) : custom).length > 0;\n  if (!hasEmail && !hasPhone && !hasCustom) {\n    throw new Error('At least one of email, phone, or custom must be provided');\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await searchContact(params);\n} catch (e) {\n  if (e.error === 'error-invalid-params') {\n    console.error('At least one search criterion (email, phone, or custom) is required.');\n    return;\n  }\n  throw e;\n}","preventionTips":["Validate that at least one search field is non-empty before submitting the form.","Disable the search button in the UI until at least one field has input."],"tags":["omnichannel","contact","validation"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}