JamesNK/Newtonsoft.Json · error · ArgumentException

Can not convert {0} to String.

Error message

Can not convert {0} to String.

What it means

Thrown by the explicit cast operator 'operator string?(JToken?)' when the token cannot be resolved to a scalar JValue. StringTypes is the broadest set ({Date, Integer, Float, String, Comment, Raw, Boolean, Bytes, Guid, TimeSpan, Uri}) and the overload is nullable (so JSON null returns null). Therefore this throw is ONLY reached when the token is not a JValue at all — i.e. a JObject, JArray, or JConstructor (EnsureValue returns null).

Source

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

            return Convert.ToSingle(v.Value, CultureInfo.InvariantCulture);
        }

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

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

            if (v.Value == null)
            {
                return null;
            }

            if (v.Value is byte[] bytes)
            {
                return Convert.ToBase64String(bytes);
            }

#if HAVE_BIG_INTEGER
            if (v.Value is BigInteger integer)
            {
                return integer.ToString(CultureInfo.InvariantCulture);
            }
#endif

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Check token["name"] is a JValue (or token["name"]?.Type != JTokenType.Object/Array) before the string cast.
  2. If the field is an object, navigate to the nested string scalar (e.g. payload["name"]["full"]).
  3. Use token["name"]?.ToString() or token.Value<string>("name") which return null instead of throwing for object/array nodes.
  4. Re-examine the indexing path; this error almost always means you are one level too shallow or too deep.

Example fix

// before
string name = (string)payload["name"]; // throws when name is an object

// after
string name = (payload["name"] is JValue) ? (string)payload["name"]! : null;
Defensive patterns

Strategy: type-guard

Validate before calling

string? name = (payload["name"] is JValue) ? (string)payload["name"]! : null;

Type guard

static bool IsScalar(JToken? t) => t is JValue;

Try / catch

string? name;
try { name = (string)payload["name"]; }
catch (ArgumentException) { name = null; }

Prevention

When it happens

Trigger: Calling (string)token["name"] where the node is a JSON object {...} or array [...] instead of a scalar, or the node is a JConstructor. Scalars of every kind (numbers, dates, GUIDs, null) convert fine and do not throw here.

Common situations: Indexing payload["name"] and accidentally grabbing a child object (e.g. { "first": ..., "last": ... }); array-valued field where a string was expected; schema change that nested the scalar inside an object.

Related errors


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