apache/pulsar · error · UnsupportedOperationException

Cannot convert from to . Requested converter does not exist

Error message

Cannot convert from  to . Requested converter does not exist.

What it means

FieldParser.convert() only supports a fixed set of source->target conversions (String<->Integer/Long/Double/Float/Boolean, direct casts, and String->enum). If the source object's type and target type do not match any registered converter, it throws UnsupportedOperationException. It exists to fail fast instead of silently returning a wrong-typed value during reflective config-field population.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/FieldParser.java:119

            // Converting string to enum
            DeserializationConfig deserializationConfig =
                    ObjectMapperFactory.getMapper().getObjectMapper().getDeserializationConfig();
            // No replacement API available in Jackson 2.x
            AnnotatedClass annotatedEnum = AnnotatedClassResolver.resolve(
                    deserializationConfig,
                    deserializationConfig.getTypeFactory().constructType(to),
                    deserializationConfig
            );
            EnumResolver r = EnumResolver.constructUsingToString(deserializationConfig, annotatedEnum);
            T value = (T) r.findEnum((String) from);
            if (value == null) {
                throw new RuntimeException("Invalid value '" + from + "' for enum " + to);
            }
            return value;
        }

        if (converter == null) {
            throw new UnsupportedOperationException("Cannot convert from " + from.getClass().getName() + " to "
                    + to.getName() + ". Requested converter does not exist.");
        }

        // Convert the value.
        try {
            Object val = converter.invoke(to, from);
            return to.cast(val);
        } catch (Exception e) {
            throw new RuntimeException("Cannot convert from " + from.getClass().getName() + " to " + to.getName()
                    + ". Conversion failed with " + e.getMessage(), e);
        }
    }

    /**
     * Update given Object attribute by reading it from provided map properties.
     *
     * @param properties
     *            which key-value pair of properties to assign those values to given object

View on GitHub (pinned to 820761864e)

Solutions

  1. Change the field type (or the source value) to one of the supported types: String, Integer, Long, Double, Float, Boolean, enum, or collections thereof.
  2. If the source is a String but the target is unsupported, pre-convert the value yourself before calling convert/update.
  3. Add a public static converter method with the signature Target converter(Source) to a helper class if you control the code, or extend FieldParser with a new converter method pair (e.g. stringToLocalDate).
  4. Check the exception message: it names the exact source and target class names that have no converter registered.

Example fix

// before
Duration d = FieldParser.convert("5000", Duration.class); // UnsupportedOperationException
// after
long millis = FieldParser.convert("5000", Long.class);
Duration d = Duration.ofMillis(millis);
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<Class<?>> SUPPORTED = Set.of(String.class, Integer.class, Long.class, Double.class, Float.class, Boolean.class);
static <T> void checkConvertible(Object from, Class<T> to) {
    if (from != null && !to.isAssignableFrom(from.getClass())
            && !SUPPORTED.contains(from.getClass()) && !to.isEnum()) {
        throw new IllegalArgumentException("no FieldParser converter for "
                + from.getClass().getName() + " -> " + to.getName());
    }
}

Type guard

static boolean isSimpleConvertibleType(Class<?> c) {
    return String.class.equals(c) || Number.class.isAssignableFrom(c)
            || Boolean.class.equals(c) || (c.isEnum() && c.getSuperclass() != null && c.getSuperclass().isEnum());
}

Try / catch

try {
    T v = FieldParser.convert(from, to);
} catch (UnsupportedOperationException e) {
    // no registered converter for this type pair — handle/prefill manually
    log.warn("unsupported conversion", e);
}

Prevention

When it happens

Trigger: Calling FieldParser.convert(obj, Target.class) where obj's runtime class has no registered converter, e.g. convert(42L, Integer.class), convert("abc", LocalDate.class), or a List<String> field whose element type is a non-String/number type reached via stringToList/stringToSet/stringToMap.

Common situations: Populating a Pulsar config object (FieldParser.update) from a properties map where a field is of an unsupported type (Instant, custom POJO, Map with non-primitive values); passing a non-String source to convert(); typos in generic type parameters on config fields.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/a9f102406ed54a9e. Report an issue: GitHub.