apache/druid · error · DruidException

defensive

defensive

Error message

Engine [%s] is unable to recognize the feature [%s] for availability. This might happen when a newer feature is added without updating all the implementations of SqlEngine(s) to either allow or disallow its availability. Please raise an issue if you encounter this exception while using Druid.

What it means

MSQTaskSqlEngine.featureAvailable hits its default case when asked about a SupportFeature it does not explicitly handle; SqlEngines.generateUnrecognizedFeatureException produces a DruidException (defensive code) saying the engine cannot recognize the feature for availability. Druid treats this as a programming bug: a new SupportFeature enum constant was added without updating every SqlEngine implementation.

Solutions

  1. Add the new feature constant to MSQTaskSqlEngine.featureAvailable with the correct availability.
  2. Audit every SqlEngine implementation (native, MSQ task, others) for exhaustive switch handling of the enum.
  3. Ensure any custom engine extension is rebuilt against the current Druid version.
  4. File/track an upstream issue if this occurs with an official Druid build, as the message requests.

Example fix

// before
case CAN_REPLACE:
case READ_EXTERNAL_DATA:
case WRITE_EXTERNAL_DATA:
case SCAN_ORDER_BY_NON_TIME:
  return true;
default:
  throw SqlEngines.generateUnrecognizedFeatureException(...);
// after
case NEW_FEATURE: // newly added SupportFeature
  return false;
case CAN_REPLACE:
...
  return true;
default:
  throw SqlEngines.generateUnrecognizedFeatureException(...);
Defensive patterns

Strategy: try-catch

Validate before calling

// Exhaustiveness check: ensure every SupportFeature constant is handled
for (SupportFeature f : SupportFeature.values()) { engine.featureAvailable(f); } // throws on unhandled constants at startup/test time

Try / catch

try { engine.featureAvailable(feature); }
catch (DruidException e) { if (e.getMessage().contains("unable to recognize the feature")) { throw new IllegalStateException("SqlEngine " + engine + " is missing a case for " + feature + "; update featureAvailable"); } throw e; }

Prevention

When it happens

Trigger: Adding a new SupportFeature enum value and running a query through the MSQ task engine without adding the case to MSQTaskSqlEngine.featureAvailable; custom SqlEngine forks enumerating features incompletely.

Common situations: Developers extending Druid's SQL engines with new features (e.g. a new CAN_* capability) and only updating some engines; upgrading Druid with custom engine extensions that lag the core enum.

Related errors


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

Appendix: source

Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/sql/MSQTaskSqlEngine.java:173

      case TIMESERIES_QUERY:
      case TOPN_QUERY:
      case TIME_BOUNDARY_QUERY:
      case GROUPING_SETS:
      case ALLOW_TOP_LEVEL_UNION_ALL:
      case GROUPBY_IMPLICITLY_SORTS:
        return false;
      case WINDOW_FUNCTIONS:
      case WINDOW_LEAF_OPERATOR:
      case UNNEST:
      case CAN_SELECT:
      case CAN_INSERT:
      case CAN_REPLACE:
      case READ_EXTERNAL_DATA:
      case WRITE_EXTERNAL_DATA:
      case SCAN_ORDER_BY_NON_TIME:
        return true;
      default:
        throw SqlEngines.generateUnrecognizedFeatureException(MSQTaskSqlEngine.class.getSimpleName(), feature);
    }
  }

  @Override
  public QueryMaker buildQueryMakerForSelect(
      final RelRoot relRoot,
      final PlannerContext plannerContext
  )
  {
    validateSelect(plannerContext);

    return new MSQTaskQueryMaker(
        null,
        overlordClient,
        plannerContext,
        relRoot.fields,
        terminalStageSpecFactory
    );

View on GitHub (pinned to 9b90983fd2)