bazelbuild/bazel · error · UnsupportedOperationException

This converter doesn't support Starlark reversal.

Error message

This converter doesn't support Starlark reversal.

What it means

Converter.reverseForStarlark(Object) is a default interface method that throws UnsupportedOperationException. Bazel calls it to render a parsed option value back into a form Starlark can consume (e.g. when exporting flag values into Starlark build settings); converters that do not opt in by overriding both starlarkConvertible() and reverseForStarlark() fail with this exception instead of silently producing a wrong string.

Source

Thrown at src/main/java/com/google/devtools/common/options/Converter.java:63

  default boolean starlarkConvertible() {
    return false;
  }

  /**
   * If {@link #starlarkConvertible()} is true, this reverses a converted value back to a
   * Starlark-readable form.
   *
   * <p>If {@link #starlarkConvertible()} is true, throws an {@link UnsupportedOperationException}.
   *
   * @param converted If the option this value represents isn't {@link Option#allowMultiple}, an
   *     object of the option's Java type. Else an entry in the option's {@link java.util.List}.
   *     Always of type T. Referenced as an {@link Object} because calling code can call any
   *     converter.
   * @return A {@link String} version of the input. Calling {@link #convert} on this value should
   *     faithfully reproduce {@code converted}.
   */
  default String reverseForStarlark(Object converted) {
    throw new UnsupportedOperationException("This converter doesn't support Starlark reversal.");
  }

  /** A converter that never reads its context parameter. */
  abstract class Contextless<T> implements Converter<T> {

    /**
     * Actual implementation of {@link #convert(String, Object)} that just ignores the context
     * parameter.
     */
    public abstract T convert(String input) throws OptionsParsingException;

    @Override
    public final T convert(String input, @Nullable Object conversionContext)
        throws OptionsParsingException {
      return convert(input);
    }
  }
}

View on GitHub (pinned to e6e199d060)

Solutions

  1. Override starlarkConvertible() to return true and provide a reverseForStarlark() whose output convert() accepts back (round-trip must be faithful).
  2. If the value cannot round-trip, redesign the value type (e.g. use a String-keyed representation) rather than throwing.
  3. Reuse a built-in converter from Converters that already supports reversal instead of writing a custom one.

Example fix

// before
class MyConverter implements Converter<MyValue> {
  public MyValue convert(String input) {...}
}
// after
class MyConverter implements Converter<MyValue> {
  public MyValue convert(String input) {...}
  @Override public boolean starlarkConvertible() { return true; }
  @Override public String reverseForStarlark(Object converted) {
    return ((MyValue) converted).toFlagString(); // convert(toFlagString()) == converted
  }
}
Defensive patterns

Strategy: type-guard

Type guard

static boolean canReverseForStarlark(Converter<?> c) {
  return c.starlarkConvertible(); // callers must check before reverseForStarlark()
}

Prevention

When it happens

Trigger: Writing a custom Converter used by an option that later gets exposed to Starlark (e.g. a Starlark-defined build setting or a command that round-trips option values), and Bazel code invokes reverseForStarlark() on the converter without checking starlarkConvertible() first; overriding convert() only is not enough.

Common situations: Third-party Bazel extensions adding custom --@foo//:bar flags with bespoke converters; upgrading Bazel versions where more option surfaces now require Starlark reversal; tests that assert round-trip fidelity of converters.

Related errors


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