{"record":{"id":"9085db3c6224df33","repo":"bazelbuild/bazel","slug":"this-converter-doesn-t-support-starlark-reversal","errorCode":null,"errorMessage":"This converter doesn't support Starlark reversal.","messagePattern":"This converter doesn't support Starlark reversal\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/google/devtools/common/options/Converter.java","lineNumber":63,"sourceCode":"  default boolean starlarkConvertible() {\n    return false;\n  }\n\n  /**\n   * If {@link #starlarkConvertible()} is true, this reverses a converted value back to a\n   * Starlark-readable form.\n   *\n   * <p>If {@link #starlarkConvertible()} is true, throws an {@link UnsupportedOperationException}.\n   *\n   * @param converted If the option this value represents isn't {@link Option#allowMultiple}, an\n   *     object of the option's Java type. Else an entry in the option's {@link java.util.List}.\n   *     Always of type T. Referenced as an {@link Object} because calling code can call any\n   *     converter.\n   * @return A {@link String} version of the input. Calling {@link #convert} on this value should\n   *     faithfully reproduce {@code converted}.\n   */\n  default String reverseForStarlark(Object converted) {\n    throw new UnsupportedOperationException(\"This converter doesn't support Starlark reversal.\");\n  }\n\n  /** A converter that never reads its context parameter. */\n  abstract class Contextless<T> implements Converter<T> {\n\n    /**\n     * Actual implementation of {@link #convert(String, Object)} that just ignores the context\n     * parameter.\n     */\n    public abstract T convert(String input) throws OptionsParsingException;\n\n    @Override\n    public final T convert(String input, @Nullable Object conversionContext)\n        throws OptionsParsingException {\n      return convert(input);\n    }\n  }\n}","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/bazelbuild/bazel/blob/e6e199d0601a244511b4cf18c8b2828aa73db1fd/src/main/java/com/google/devtools/common/options/Converter.java#L45-L81","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Override starlarkConvertible() to return true and provide a reverseForStarlark() whose output convert() accepts back (round-trip must be faithful).","If the value cannot round-trip, redesign the value type (e.g. use a String-keyed representation) rather than throwing.","Reuse a built-in converter from Converters that already supports reversal instead of writing a custom one."],"exampleFix":"// before\nclass MyConverter implements Converter<MyValue> {\n  public MyValue convert(String input) {...}\n}\n// after\nclass MyConverter implements Converter<MyValue> {\n  public MyValue convert(String input) {...}\n  @Override public boolean starlarkConvertible() { return true; }\n  @Override public String reverseForStarlark(Object converted) {\n    return ((MyValue) converted).toFlagString(); // convert(toFlagString()) == converted\n  }\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean canReverseForStarlark(Converter<?> c) {\n  return c.starlarkConvertible(); // callers must check before reverseForStarlark()\n}","tryCatchPattern":null,"preventionTips":["Custom converters destined for Starlark-visible options must override starlarkConvertible() and reverseForStarlark() together.","Unit-test the round trip: convert(reverseForStarlark(v)) equals v for representative values.","Check starlarkConvertible() before calling reverseForStarlark() on converters you do not own."],"tags":["bazel","options-api","starlark","converter","custom-converter"],"backgroundTag":null,"analyzedSha":"e6e199d0601a244511b4cf18c8b2828aa73db1fd","analyzedAt":"2026-08-14T10:24:27.848Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}