XINCGer/Unity3DTraining · error · ArgumentException

Unable to format value of type

Error message

Unable to format value of type 

What it means

JsonFormatter.WriteValue throws ArgumentException when the runtime value is not one of the types the formatter can serialize (bool, numeric types, string, ByteString, IMessage, enumerables, IFormattable enums, etc.). The formatter is strictly typed and refuses unknown object shapes.

Solutions

  1. Ensure messages are generated Google.Protobuf types (implement IMessage properly)
  2. Convert unsupported values (e.g. DateTime) to protobuf-compatible types or well-known wrappers (Timestamp/Duration) before formatting
  3. Check any custom WriteValue/WriteWellKnownTypeValue extension code for passing raw objects
  4. Use a custom JsonFormatter.Settings formatter hook for exotic values

Example fix

// before
writer.WriteValue(myDateTime);
// after
var ts = Timestamp.FromDateTime(myDateTime); formatter.Format(ts, writer);
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure field values are protobuf-native types before formatting
if (value is IMessage || value is string || value is int || value is long || value is float || value is double || value is bool || value is ByteString) { formatter.Format(msg); }

Try / catch

try { writer = formatter.Format(msg); } catch (ArgumentException ex) { /* handle unsupported value type: ex.Message contains the type */ }

Prevention

When it happens

Trigger: Formatting a message field whose runtime value is an unsupported CLR type, e.g. a custom class, DateTime, or a null-adjacent value that fell through all type checks in WriteValue's if/else chain.

Common situations: Custom message implementations not derived from generated IMessage<T> code; inserting foreign objects into maps/lists of a message via reflection; writing custom well-known-type handlers that pass raw values to WriteValue.

Related errors


AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12). Data as JSON: /api/errors/36820488c752ce2b. Report an issue: GitHub.

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonFormatter.cs:414

                string text = ((IFormattable)value).ToString("r", CultureInfo.InvariantCulture);
                if (text == "NaN" || text == "Infinity" || text == "-Infinity")
                {
                    writer.Write('"');
                    writer.Write(text);
                    writer.Write('"');
                }
                else
                {
                    writer.Write(text);
                }
            }
            else if (value is IMessage)
            {
                Format((IMessage)value, writer);
            }
            else
            {
                throw new ArgumentException("Unable to format value of type " + value.GetType());
            }
        }

        /// <summary>
        /// Central interception point for well-known type formatting. Any well-known types which
        /// don't need special handling can fall back to WriteMessage. We avoid assuming that the
        /// values are using the embedded well-known types, in order to allow for dynamic messages
        /// in the future.
        /// </summary>
        private void WriteWellKnownTypeValue(TextWriter writer, MessageDescriptor descriptor, object value)
        {
            // Currently, we can never actually get here, because null values are always handled by the caller. But if we *could*,
            // this would do the right thing.
            if (value == null)
            {
                WriteNull(writer);
                return;
            }

View on GitHub (pinned to 016f98412e)