{"record":{"id":"4d7925d18136e58f","repo":"ToolJet/ToolJet","slug":"query-could-not-be-completed-4d7925","errorCode":null,"errorMessage":"Query could not be completed","messagePattern":"Query could not be completed","errorType":"exception","errorClass":"QueryError","httpStatus":null,"severity":"error","filePath":"plugins/packages/elasticsearch/lib/index.ts","lineNumber":72,"sourceCode":"          break;\n        case 'scroll':\n          result = await scrollSearch(client, queryOptions.scroll_id, queryOptions.scroll);\n          break;\n        case 'clear_scroll':\n          result = await clearScroll(client, queryOptions.scroll_id);\n          break;\n        case 'cat_indices':\n          result = await getCatIndices(client);\n          break;\n        case 'cluster_health':\n          result = await getClusterHealth(client);\n          break;\n        default:\n          throw new Error(`Unsupported operation: ${operation}`);\n      }\n    } catch (err) {\n      console.log(err);\n      throw new QueryError('Query could not be completed', err.message, {});\n    }\n\n    return {\n      status: 'ok',\n      data: result,\n    };\n  }\n\n  async testConnection(sourceOptions: SourceOptions): Promise<ConnectionTestResult> {\n    try {\n      const client = await this.getConnection(sourceOptions);\n      await client.info();\n      return {\n        status: 'ok',\n        message: 'Connection successful',\n      };\n    } catch (err: any) {\n      const errorMessage = err || 'Unknown error';","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/ToolJet/ToolJet/blob/20602a8e101f2e59686c9afde0d1402aac2c8871/plugins/packages/elasticsearch/lib/index.ts#L54-L90","documentation":"The Elasticsearch run() method wraps its entire operation switch in one try/catch. Any failure — SDK transport error, missing index, malformed query DSL, auth rejection, the 'Unsupported operation' default throw — is normalized into a QueryError titled 'Query could not be completed' with the original err.message as description. The original error object is not preserved in data (an empty object is passed). A console.log(err) also leaks the full error to server logs.","triggerScenarios":"Network/TLS error reaching the OpenSearch/Elasticsearch node. Auth failure (wrong credentials, encoded username/password mismatch). Index not found on search/get. Malformed query body (JSON parse or DSL validation). Bulk operation with a malformed actions array. Scroll using an expired or unknown scroll_id. cat_indices/cluster_health failing because the user lacks cluster permissions.","commonSituations":"Host/port/protocol misconfiguration in the datasource (http vs https, wrong port). Self-signed cert without the CA configured. Username/password with special characters not URL-encoded (getConnection uses encodeURIComponent, but a stale config may pre-encode). Querying a deleted index. Scroll context expired (>1m keep-alive). Cluster权限 insufficient for cat APIs.","solutions":["Read the QueryError.description — it carries the underlying transport/DSL message which identifies the real cause.","Verify host, port, protocol (determineProtocol logic), and credentials in the datasource; re-run test connection.","If SSL is on, provide the correct CA / client cert / key in the datasource SSL fields.","For query DSL errors, validate the body JSON against the cluster's mapping before sending.","For scroll errors, re-issue the initial search to obtain a fresh scroll_id."],"exampleFix":"// before — index name typo causes NotFound\nqueryOptions = { operation: 'search', index: 'order', query: {...} };\n// after\nqueryOptions = { operation: 'search', index: 'orders', query: {...} };","handlingStrategy":"try-catch","validationCode":"function validateEsQuery(qo) {\n  if (qo.operation === 'search' && !qo.index) throw new Error('index required for search');\n  if (['get','update','delete','exists'].includes(qo.operation) && !qo.id) throw new Error('id required for ' + qo.operation);\n  if (qo.operation === 'bulk' && !Array.isArray(qo.operations)) throw new Error('operations array required for bulk');\n}","typeGuard":null,"tryCatchPattern":"try { await plugin.run(sourceOptions, queryOptions); }\ncatch (e) { if (e instanceof QueryError && e.message === 'Query could not be completed') { console.error('ES detail:', e.description); /* e.description is the transport/DSL message */ } else throw e; }","preventionTips":["Validate the query DSL JSON against the cluster mapping before sending.","Confirm host/port/protocol/credentials with testConnection first.","Provide the correct SSL CA when TLS is enabled."],"tags":["elasticsearch","opensearch","query-error","transport","tooljet"],"backgroundTag":null,"analyzedSha":"20602a8e101f2e59686c9afde0d1402aac2c8871","analyzedAt":"2026-08-13T05:58:54.221Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}