apache/druid · error · DruidException

Could not convert task[%s] to compatible object.

Error message

Could not convert task[%s] to compatible object.

What it means

LocalOverlordClient.convertTask() fails when Jackson cannot deserialize/serialize the task payload into the requested outputType (client-compatible object). On IOException it logs a warning and throws a defensive DruidException 'Could not convert task[%s] to compatible object.', indicating an internal invariant violation since task payloads should be convertible.

Source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/compact/LocalOverlordClient.java:190

  {
    if (taskPayload == null) {
      return null;
    } else if (!inputType.isInstance(taskPayload)) {
      throw DruidException.defensive(
          "Unknown type[%s] for compaction task. Expected type[%s].",
          taskPayload.getClass().getSimpleName(), inputType.getSimpleName()
      );
    }

    try {
      return objectMapper.readValue(
          objectMapper.writeValueAsBytes(taskPayload),
          outputType
      );
    }
    catch (IOException e) {
      log.warn(e, "Could not convert task[%s] to client compatible object", taskPayload);
      throw DruidException.defensive(
          "Could not convert task[%s] to compatible object.",
          taskPayload
      );
    }
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure the task's type is registered in the injector's polymorphic ObjectMapper (register the task module/subtypes).
  2. Inspect the task payload in the metadata storage for corruption or schema drift.
  3. Align versions of indexing-service classes between writer and reader of the payload.
  4. File a bug if the payload is a standard Druid task type, since this is a defensive invariant failure.

Example fix

// before
// Custom task class not registered -> convertTask throws DruidException
// after
// register the subtype so Jackson can map it
objectMapper.registerSubtypes(MyCustomTask.class);
Defensive patterns

Strategy: try-catch

Validate before calling

// Before querying, confirm the task type is registered
if (!knownTaskTypes.contains(task.getType())) { throw new IllegalArgumentException("Unknown task type: " + task.getType()); }

Try / catch

try { Task t = client.task(taskId); } catch (DruidException e) { if (e.getMessage().contains("Could not convert task")) { /* inspect payload / register subtype */ } }

Prevention

When it happens

Trigger: task/taskPayload call encountering an IOException from objectMapper.readValue(taskJson, outputType) — e.g. task JSON incompatible with the expected type or missing modules.

Common situations: Custom task types not registered with the ObjectMapper (missing module/ subtype registration); corrupted or hand-edited task payloads in metadata storage; version skew between overlord and client task classes.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/e0d70e4865a85ebc. Report an issue: GitHub.