bazelbuild/bazel · error · OptionProcessorException

Cannot find valid converter for option of type %s

Error message

Cannot find valid converter for option of type %s

What it means

After failing to match any registered default converter for the option's type (during default-value validation), Bazel's options annotation processor reports this error: no built-in converter exists for the option's return type. Options must either use a type with a known default converter or supply an explicit converter via the @Option converter attribute.

Source

Thrown at src/main/java/com/google/devtools/common/options/processor/OptionsClassProcessor.java:634

      Converter<?> converterInstance = findDefaultConverter(acceptedConverterReturnType);
      if (converterInstance == null) {
        continue;
      }
      try {
        converterInstance.convert(defaultValue, null);
      } catch (OptionsParsingException e) {
        TypeElement converter =
            elementUtils.getTypeElement(converterInstance.getClass().getCanonicalName());
        throw new OptionProcessorException(
            method,
            e,
            "Option lists a default value (%s) that is not parsable by the option's converter (%s)",
            defaultValue,
            converter);
      }
      return;
    }
    throw new OptionProcessorException(
        method,
        "Cannot find valid converter for option of type %s",
        acceptedConverterReturnTypes.get(0));
  }

  @Nullable
  private Converter<?> findDefaultConverter(TypeMirror type) {
    // According to the documentation of TypeMirror, equality check is not how one checks whether
    // two instances reference the same type but Types.isSameType().
    for (Map.Entry<TypeMirror, Converter<?>> entry : defaultConverters.entrySet()) {
      if (typeUtils.isSameType(type, entry.getKey())) {
        return entry.getValue();
      }
    }
    return null;
  }

  private void checkProvidedConverter(

View on GitHub (pinned to e6e199d060)

Solutions

  1. Write a class implementing Converter<MyType> (convert(String, Object) returning MyType) and reference it: @Option(..., converter = MyTypeConverter.class).
  2. Or change the option's type to one with a default converter (String, boolean, int, long, List<E> of those, etc.).
  3. If a suitable converter already exists in the codebase (search for 'implements Converter'), reuse it via the converter attribute rather than writing a new one.
  4. Recompile to confirm.

Example fix

// before
@Option(
  name = "custom_timeout",
  defaultValue = "30s"
)
public static DurationSpec customTimeout;  // no default converter
// after
@Option(
  name = "custom_timeout",
  defaultValue = "30s",
  converter = DurationSpecConverter.class
)
public static DurationSpec customTimeout;
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the option type has a default converter or an explicit one is supplied
static void assertConvertible(TypeMirror optionType,
                              Map<TypeMirror, Converter<?>> defaultConverters,
                              Class<? extends Converter<?>> explicitConverter) {
  boolean hasDefault = defaultConverters.keySet().stream()
      .anyMatch(t -> t.equals(optionType));
  Preconditions.checkState(hasDefault || explicitConverter != null,
      "No default converter for %s and no converter attribute set", optionType);
}

Prevention

When it happens

Trigger: An @Option method whose return type has no entry in the processor's defaultConverters map and no explicit converter attribute — e.g. a custom class like MyCustomType, or a type whose only available converter is not registered with the processor.

Common situations: Adding options for domain types (paths, durations with custom formats, enums with special parsing) without writing a Converter; depending on a converter registered at runtime but unknown to the annotation processor; typos in generic element types after an allowMultiple refactor.

Related errors


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/66c5d96e0cea5ac2. Report an issue: GitHub.