apache/seatunnel · error · IllegalArgumentException

Sparse vector value must be a Number, but got: %s

Error message

Sparse vector value must be a Number, but got: %s

What it means

convertSparseVectorToFloatArray requires every value in the sparse vector map to be a java.lang.Number so it can call floatValue(). This IllegalArgumentException is thrown when a value is some other type, naming the offending value's class.

Source

Thrown at seatunnel-common/src/main/java/org/apache/seatunnel/common/utils/VectorUtils.java:164

            int index = (Integer) key;
            if (index < 0) {
                throw new IllegalArgumentException(
                        String.format("Sparse vector index cannot be negative: %d", index));
            }
            // prevent OOM
            if (index > 1000000) {
                throw new IllegalArgumentException(
                        String.format("Sparse vector index too large: %d", index));
            }
            maxIndex = Math.max(maxIndex, index);
        }
        Float[] denseVector = new Float[maxIndex + 1];
        Arrays.fill(denseVector, 0.0f);
        for (Map.Entry<?, ?> entry : sparseVector.entrySet()) {
            Object key = entry.getKey();
            Object value = entry.getValue();
            if (!(value instanceof Number)) {
                throw new IllegalArgumentException(
                        String.format(
                                "Sparse vector value must be a Number, but got: %s",
                                value.getClass().getName()));
            }
            int index = (Integer) key;
            denseVector[index] = ((Number) value).floatValue();
        }
        return denseVector;
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Inspect the logged class name and convert values to a numeric type before the call (e.g. Float.parseFloat(str)).
  2. Fix the deserialization layer so numbers stay numeric (use a JSON mapper that infers number types).
  3. Ensure the map is typed Map<Integer, ? extends Number> at the call site.
  4. Pre-validate all values with instanceof Number and reject/convert non-numeric entries.

Example fix

// before
Map<String, String> raw = Map.of("0", "0.5");
Float[] dense = VectorUtils.convertSparseVectorToFloatArray(raw); // throws
// after
Map<Integer, Float> v = raw.entrySet().stream()
    .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey()), e -> Float.parseFloat(e.getValue())));
Float[] dense2 = VectorUtils.convertSparseVectorToFloatArray(v);
Defensive patterns

Strategy: type-guard

Validate before calling

boolean allNumeric(Map<?,?> v) { return v.values().stream().allMatch(x -> x instanceof Number); }

Type guard

boolean isNumber(Object o) { return o instanceof Number; }

Try / catch

try { Float[] d = VectorUtils.convertSparseVectorToFloatArray(v); } catch (IllegalArgumentException e) { /* convert value types per the message and retry */ }

Prevention

When it happens

Trigger: Passing a Map<?, ?> whose values are Strings, boxed-but-stringified decimals, or arbitrary objects instead of numeric types; typically when the sparse vector comes from deserialized JSON/config where numbers became strings.

Common situations: Parsing sparse vectors from JSON where floats were serialized as strings ('0.5'), building vectors from raw config maps (Typesafe Config returns heterogeneous types), or schema drift in an upstream producer.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/fc2075e3e5fcd9e4. Report an issue: GitHub.