CoplayDev/unity-mcp · error · ValueError

{context} dict values must be numeric, got {value}

Error message

{context} dict values must be numeric, got {value}

What it means

Raised by _normalize_color (texture.py:126) when the value is a dict containing r/g/b keys but one or more of its values cannot be converted to a float (TypeError or ValueError during the numeric conversion). The 'context' label names the offending field (e.g. 'set-pixels color dict values must be numeric...'). This is the dict branch of color normalization; a correctly-keyed dict with non-numeric values triggers it.

Source

Thrown at Server/src/cli/commands/texture.py:126

    if isinstance(value, str):
        if value.startswith("#"):
            return _parse_hex_color(value)
        value = try_parse_json(value, context)

    # Handle dict with r/g/b keys (e.g., {"r": 1, "g": 0, "b": 0} or {"r": 1, "g": 0, "b": 0, "a": 1})
    if isinstance(value, dict):
        if all(k in value for k in ("r", "g", "b")):
            try:
                color = [value["r"], value["g"], value["b"]]
                if "a" in value:
                    color.append(value["a"])
                else:
                    color.append(1.0 if _is_normalized_color(color) else 255)
                if _is_normalized_color(color):
                    return [int(round(float(c) * 255)) for c in color]
                return [int(c) for c in color]
            except (TypeError, ValueError):
                raise ValueError(f"{context} dict values must be numeric, got {value}")
        raise ValueError(f"{context} dict must have 'r', 'g', 'b' keys, got {list(value.keys())}")

    if isinstance(value, (list, tuple)):
        if len(value) == 3:
            value = list(value) + [1.0 if _is_normalized_color(value) else 255]
        if len(value) == 4:
            try:
                if _is_normalized_color(value):
                    return [int(round(float(c) * 255)) for c in value]
                return [int(c) for c in value]
            except (TypeError, ValueError):
                raise ValueError(
                    f"{context} values must be numeric, got {value}")
        raise ValueError(
            f"{context} must have 3 or 4 components, got {len(value)}")

    raise ValueError(f"{context} must be a list or hex string")

View on GitHub (pinned to c21bf496bc)

Solutions

  1. Make every r/g/b(/a) value a number (int or float) in 0-255 or normalized 0-1 form.
  2. Remove quotes around numeric values in the JSON dict.
  3. Replace null channel values with an explicit number (e.g. alpha 255 or 1.0).

Example fix

# before
unity-mcp texture create Assets/Tex.png --color '{"r":"red","g":0,"b":0}'

# after
unity-mcp texture create Assets/Tex.png --color '{"r":255,"g":0,"b":0}'
Defensive patterns

Strategy: type-guard

Validate before calling

# Python - before normalizing a dict color
if isinstance(value, dict):
    for k in ("r", "g", "b"):
        if not isinstance(value.get(k), (int, float)) or isinstance(value.get(k), bool):
            raise ValueError(f"{context} dict values must be numeric, got {value}")

Type guard

def is_numeric_color_dict(v) -> bool:
    return isinstance(v, dict) and all(k in v for k in ("r","g","b")) and all(isinstance(v[k],(int,float)) and not isinstance(v[k],bool) for k in ("r","g","b"))

Try / catch

try:
    color = _normalize_color(value, context)
except ValueError as e:
    print_error(str(e)); sys.exit(1)

Prevention

When it happens

Trigger: Passing a color dict like {"r": "red", "g": 0, "b": 0} or {"r": null, "g": 1, "b": 1} via --color, --palette, a pixels array, or set-pixels color. Any r/g/b(/a) value that float() cannot parse hits this.

Common situations: Pasting a Unity color object that uses string color names; mixing types (a string in one channel); a value of null in a channel; a dict produced by JSON where numbers were quoted.

Related errors


AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13). Data as JSON: /api/errors/e4597a0552f3988b. Report an issue: GitHub.