CoplayDev/unity-mcp · error · JsonException

Failed to parse float at index

Error message

Failed to parse float at index {i}: '{arr[i]}'

What it means

ParseFloatArray iterates a JArray and calls ToObject<float> on each element. When an element cannot be converted to float, the exception is rethrown with the failing index and the raw token value for diagnosis.

Solutions

  1. Ensure every element of the array is a numeric value.
  2. Validate the array contents before sending the command.
  3. If sending a single value, pass it directly (the function coerces a single value to a one-element array).

Example fix

// before
{ "orbit_elevations": ["low", 30, 60] }
// after
{ "orbit_elevations": [10, 30, 60] }
Defensive patterns

Strategy: type-guard

Validate before calling

if (token.Type == JTokenType.Array)
{
    for (int i = 0; i < token.Count(); i++)
        if (token[i].Type != JTokenType.Float && token[i].Type != JTokenType.Integer)
            throw new ArgumentException($"Array element {i} is not numeric: '{token[i]}'");
}

Type guard

static bool IsNumericArray(JToken t)
{
    if (t == null || t.Type == JTokenType.Null) return true;
    if (t.Type == JTokenType.Float || t.Type == JTokenType.Integer) return true;
    if (t.Type != JTokenType.Array) return false;
    foreach (var e in t)
        if (e.Type != JTokenType.Float && e.Type != JTokenType.Integer) return false;
    return true;
}

Prevention

When it happens

Trigger: A float-array parameter (e.g. orbit_elevations, position/rotation arrays) contains a non-numeric value: a string like 'high', null, a boolean, or a nested object/array.

Common situations: An LLM sends strings instead of numbers; a payload mixes types; a caller reuses a value meant for another field.

Understand the failure class

Related errors


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

Appendix: source

Thrown at MCPForUnity/Editor/Tools/ManageScene.cs:84

            public bool? autoRepair { get; set; }        // for validate with auto-repair
        }

        private static float[] ParseFloatArray(JToken token)
        {
            if (token == null || token.Type == JTokenType.Null) return null;
            if (token.Type == JTokenType.Array)
            {
                var arr = (JArray)token;
                var result = new float[arr.Count];
                for (int i = 0; i < arr.Count; i++)
                {
                    try
                    {
                        result[i] = arr[i].ToObject<float>();
                    }
                    catch (Exception ex)
                    {
                        throw new Newtonsoft.Json.JsonException(
                            $"Failed to parse float at index {i}: '{arr[i]}'", ex);
                    }
                }
                return result;
            }
            // Single value → array of one
            var single = ParamCoercion.CoerceFloatNullable(token);
            return single.HasValue ? new[] { single.Value } : null;
        }

        private static SceneCommand ToSceneCommand(JObject p)
        {
            if (p == null) return new SceneCommand();
            var toolParams = new ToolParams(p);
            return new SceneCommand
            {
                action = (p["action"]?.ToString() ?? string.Empty).Trim().ToLowerInvariant(),
                name = p["name"]?.ToString() ?? string.Empty,

View on GitHub (pinned to c21bf496bc)