{"record":{"id":"b30687e9dd54eb1d","repo":"apache/druid","slug":"log-streaming-not-supported-by-s","errorCode":null,"errorMessage":"Log streaming not supported by [%s]","messagePattern":"Log streaming not supported by \\[(.+?)\\]","errorType":"http","errorClass":null,"httpStatus":501,"severity":"warning","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/worker/http/WorkerResource.java","lineNumber":176,"sourceCode":"    catch (Exception e) {\n      log.error(e, \"Failed to issue shutdown for task: %s\", taskid);\n      return Response.serverError().build();\n    }\n    return Response.ok(ImmutableMap.of(\"task\", taskid)).build();\n  }\n\n  @GET\n  @Path(\"/task/{taskid}/log\")\n  @Produces(HttpMediaType.TEXT_PLAIN_UTF8)\n  @ResourceFilters(StateResourceFilter.class)\n  public Response doGetLog(\n      @PathParam(\"taskid\") String taskId,\n      @QueryParam(\"offset\") @DefaultValue(\"0\") long offset\n  )\n  {\n    IdUtils.validateId(\"taskId\", taskId);\n    if (!(taskRunner instanceof TaskLogStreamer)) {\n      return Response.status(501)\n                     .type(MediaType.TEXT_PLAIN)\n                     .entity(StringUtils.format(\n                         \"Log streaming not supported by [%s]\",\n                         taskRunner.getClass().getName()\n                     ))\n                     .build();\n    }\n    try {\n      final Optional<InputStream> stream = ((TaskLogStreamer) taskRunner).streamTaskLog(taskId, offset);\n\n      if (stream.isPresent()) {\n        return Response.ok(stream.get()).build();\n      } else {\n        return Response.status(Response.Status.NOT_FOUND).build();\n      }\n    }\n    catch (IOException e) {\n      log.warn(e, \"Failed to read log for task: %s\", taskId);","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/worker/http/WorkerResource.java#L158-L194","documentation":"WorkerResource.doGetLog returns HTTP 501 with body \"Log streaming not supported by [%s]\" when the configured TaskRunner does not implement TaskLogStreamer, so log streaming for tasks is unavailable. This is a capability check, not a data error; the runner class is named in the response.","triggerScenarios":"GET /druid/indexer/v1/worker/{taskId}/log on a Middle Manager whose TaskRunner (e.g. some remote/custom runners) does not implement TaskLogStreamer.","commonSituations":"Querying task logs through an intermediary/proxy that hits a worker with an unsupported runner type; custom TaskRunner deployments; expecting log streaming while using a runner that only supports other log access.","solutions":["Use a TaskRunner implementation that implements TaskLogStreamer (e.g. local runners) if streaming is required.","Fetch task logs from deep storage or the overlord's log endpoint instead of the worker.","Check the runner class in the 501 body and consult its documentation for log access options."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"if (!(taskRunner instanceof TaskLogStreamer)) { // use deep storage / overlord log API instead }\n","typeGuard":"if (taskRunner instanceof TaskLogStreamer streamer) { /* safe to request logs */ }","tryCatchPattern":"Response r = workerResource.doGetLog(taskId, offset);\nif (r.getStatus() == 501) { /* fall back to overlord /druid/indexer/v1/task/{id}/log */ }","preventionTips":["Know your Middle Manager's TaskRunner type before building log-access tooling.","Prefer deep-storage log retrieval for remote runners.","Handle 501 explicitly in automation rather than treating it as failure."],"tags":["http","task-runner","logs","unsupported"],"backgroundTag":"operation-not-supported","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"}