{"record":{"id":"346639b25f3af9e8","repo":"apache/druid","slug":"query-s-to-host-s-interrupted","errorCode":null,"errorMessage":"Query [%s] to host [%s] interrupted","messagePattern":"Query \\[(.+?)\\] to host \\[(.+?)\\] interrupted","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/client/JsonParserIterator.java","lineNumber":240,"sourceCode":"  }\n\n  private QueryTimeoutException timeoutQuery()\n  {\n    return new QueryTimeoutException(StringUtils.nonStrictFormat(\"url[%s] timed out\", url), host);\n  }\n\n  /**\n   * Converts the given exception to a proper type of {@link QueryException}.\n   * The use cases of this method are:\n   * <p>\n   * - All non-QueryExceptions are wrapped with {@link QueryInterruptedException}.\n   * - The QueryException from {@link DirectDruidClient} is converted to a more specific type of QueryException\n   * based on {@link QueryException#getErrorCode()}. During conversion, {@link QueryException#host} is overridden\n   * by {@link #host}.\n   */\n  private QueryException convertException(Throwable cause)\n  {\n    LOG.warn(cause, \"Query [%s] to host [%s] interrupted\", queryId, host);\n    if (cause instanceof QueryException) {\n      final QueryException queryException = (QueryException) cause;\n      if (queryException.getErrorCode() == null) {\n        // errorCode should not be null now, but maybe could be null in the past...\n        return new QueryInterruptedException(\n            QueryException.UNKNOWN_EXCEPTION_ERROR_CODE,\n            queryException.getMessage(),\n            queryException.getErrorClass(),\n            host\n        );\n      }\n\n      // Note: this switch clause is to restore the 'type' information of QueryExceptions which is lost during\n      // JSON serialization. As documented on the QueryException class, the errorCode of QueryException is the only\n      // way to differentiate the cause of the exception.  This code does not cover all possible exceptions that\n      // could come up and so, likely, doesn't produce exceptions reliably.  The only safe way to catch and interact\n      // with a QueryException is to catch QueryException and check its errorCode.  In some future code change, we\n      // should likely remove this switch entirely, but when we do that, we need to make sure to also adjust any","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/client/JsonParserIterator.java#L222-L258","documentation":"JsonParserIterator.convertException logs this warning when converting a Throwable received while pulling query results from a broker-to-historical HTTP stream into a QueryException. The original cause (e.g. a QueryException from DirectDruidClient) is preserved and rethrown with the host attached; conversion maps error codes to specific interrupt exception types.","triggerScenarios":"next()/init() on the JSON-parsed result iterator encounter an exception: the HTTP stream from the target host failed, was cancelled, or a QueryException arrived whose errorCode needs remapping.","commonSituations":"Historical node restarts mid-query, query cancellation from the console, HTTP connection drops between broker and data node, timeouts surfacing as interrupts.","solutions":["Check the logged cause and host to find the failing data node and its error code","Inspect the target host's logs for the original query failure","Retry the query if the node restarted or the connection dropped","Adjust timeout/cancellation settings if interrupts are systemic"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try { iterator.next(); } catch (QueryException e) { if (e.getErrorCode() == QUERY_CANCELED) { /* handle cancel */ } else { log.error(\"host failed: \" + e.getHost()); } }","preventionTips":["Monitor broker->historical connectivity","Handle QUERY_CANCELED and TIMEOUT error codes distinctly in clients","Retry transient stream failures from restarting nodes"],"tags":["distributed-query","http","iterator"],"backgroundTag":"http-request-failed","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}