JamesNK/Newtonsoft.Json · error · ArgumentException

Can not convert {0} to Uri.

Error message

Can not convert {0} to Uri.

What it means

Thrown by the explicit cast operator 'operator Uri?(JToken?)' (Nullable<Uri>) when the token is not a Uri-compatible JValue. ArgumentException {0} is the resolved JTokenType; allowed types are UriTypes ({String, Comment, Raw, Uri}). Nullable overload, so null/JSON-null return null. Throw means a structurally incompatible shape such as Integer, Float, Boolean, Date, Guid, Uri-typed-wrapped-but-mismatched, Object, or Array.

Source

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

            return (v.Value is TimeSpan span) ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!);
        }

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

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

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

            return (v.Value is Uri uri) ? uri : new Uri(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!);
        }

#if HAVE_BIG_INTEGER
        private static BigInteger ToBigInteger(JToken value)
        {
            JValue? v = EnsureValue(value);
            if (v == null || !ValidateToken(v, BigIntegerTypes, false))
            {
                throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
            }

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Guard token["endpoint"]?.Type is String or Uri before casting.
  2. Use Uri.TryCreate on the string value: Uri.TryCreate((string)token["endpoint"], UriKind.Absolute, out var u).
  3. If the field became a structured object, reconstruct the URL string from its parts before parsing.
  4. Prefer token.Value<Uri>("endpoint") which returns null on incompatible shapes.

Example fix

// before
Uri endpoint = (Uri)payload["endpoint"]; // throws when endpoint is an object/int

// after
Uri endpoint = Uri.TryCreate((string?)payload["endpoint"], UriKind.Absolute, out var u) ? u : null;
Defensive patterns

Strategy: validation

Validate before calling

Uri? endpoint = Uri.TryCreate((string?)payload["endpoint"], UriKind.Absolute, out var u) ? u : null;

Type guard

static bool IsUriLike(JToken? t) =>
    t is JValue v && (v.Type == JTokenType.Uri || v.Type == JTokenType.String);

Try / catch

Uri? endpoint;
try { endpoint = (Uri)payload["endpoint"]; }
catch (ArgumentException) { endpoint = null; }

Prevention

When it happens

Trigger: Calling (Uri)token["endpoint"] where the resolved JTokenType is Integer, Float, Boolean, Date, Guid, Bytes, TimeSpan, Object, or Array, or the node is a JObject/JArray/JConstructor. A malformed URI STRING passes ValidateToken then throws UriFormatException from new Uri(string), not this error.

Common situations: Endpoint field emitted as an integer port or an object { "host":..., "port":... } instead of a URL string; null URL in some records; schema change from URL string to a structured object.

Related errors


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