JamesNK/Newtonsoft.Json · error · ArgumentException

Can not convert {0} to Single.

Error message

Can not convert {0} to Single.

What it means

Thrown by the explicit cast operator 'operator float?(JToken?)' (Nullable<Single>) when the token is not resolvable to a numeric JValue. ArgumentException {0} is the resolved JTokenType; allowed types are NumberTypes ({Integer, Float, String, Comment, Raw, Boolean}). Nullable overload, so null/JSON-null return null; the throw indicates a structurally incompatible token (e.g. Date, Guid, Object, Array).

Source

Thrown at Src/Newtonsoft.Json/Linq/JToken.cs:1154

            return (v.Value != null) ? (long?)Convert.ToInt64(v.Value, CultureInfo.InvariantCulture) : null;
        }

        /// <summary>
        /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Nullable{T}"/> of <see cref="Single"/>.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The result of the conversion.</returns>
        public static explicit operator float?(JToken? value)
        {
            if (value == null)
            {
                return null;
            }

            JValue? v = EnsureValue(value);
            if (v == null || !ValidateToken(v, NumberTypes, true))
            {
                throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
            }

#if HAVE_BIG_INTEGER
            if (v.Value is BigInteger integer)
            {
                return (float?)integer;
            }
#endif

            return (v.Value != null) ? (float?)Convert.ToSingle(v.Value, CultureInfo.InvariantCulture) : null;
        }

        /// <summary>
        /// Performs an explicit conversion from <see cref="JToken"/> to <see cref="Decimal"/>.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The result of the conversion.</returns>
        public static explicit operator decimal(JToken value)

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Guard with token["rate"]?.Type in {Integer, Float, String, Boolean} before the cast.
  2. Prefer token["rate"]?.Value<float>() returning 0/null on mismatch instead of throwing.
  3. If the field became a structured object, parse the nested scalar (e.g. payload["rate"]["value"]) instead.
  4. Deserialize into a typed POCO so contract drift surfaces as clear mapping errors.

Example fix

// before
float? rate = (float?)payload["rate"]; // throws when rate is an object

// after
var rateNode = payload["rate"];
float? rate = (rateNode is JValue jv && (jv.Type == JTokenType.Float || jv.Type == JTokenType.Integer)) ? (float?)jv : null;
Defensive patterns

Strategy: validation

Validate before calling

float? rate = (payload["rate"] is JValue jv &&
    (jv.Type == JTokenType.Float || jv.Type == JTokenType.Integer)) ? (float?)jv : null;

Type guard

static bool IsNumericLike(JToken? t) =>
    t is JValue v && Array.IndexOf(
        new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Boolean }, v.Type) >= 0;

Try / catch

float? rate;
try { rate = (float?)payload["rate"]; }
catch (ArgumentException) { rate = null; }

Prevention

When it happens

Trigger: Calling (float?)token["rate"] where the resolved JTokenType is Date, Guid, TimeSpan, Uri, Bytes, Object, or Array, or the node is a JObject/JArray (EnsureValue null). A non-numeric string like "n/a" passes ValidateToken but then throws FormatException from Convert.ToSingle, not this error.

Common situations: Percentage/rate field replaced by an object (e.g. { "value": 1.5, "unit": "%" }); a null-bearing field indexed into the wrong node; third-party payload that sometimes embeds metadata objects where a scalar float is expected.

Related errors


AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07). Data as JSON: /api/errors/facaa43b9ba2a5fe. Report an issue: GitHub.