XINCGer/Unity3DTraining · error · InvalidOperationException

Value message must contain a value for the oneof.

Error message

Value message must contain a value for the oneof.

What it means

JsonFormatter.WriteStructFieldValue throws InvalidOperationException when a google.protobuf.Value message has no case set in its oneof (kind). A Value must have exactly one of null_value/number_value/string_value/bool_value/struct_value/list_value set.

Solutions

  1. Set exactly one kind before formatting, e.g. Value.ForNull(), Value.ForString("x")
  2. Check Value.HasKind / which case is set before formatting
  3. Avoid default(Value) instances; use the static For* factory methods
  4. Validate Struct contents recursively before JsonFormatter.Format

Example fix

// before
var v = new Value();
// after
var v = Value.ForNull(); // or Value.ForString("text")
Defensive patterns

Strategy: validation

Validate before calling

if (!value.HasKind) { value = Value.ForNull(); } // or appropriate kind
formatter.Format(structMsg);

Type guard

static bool HasKind(Value v) => v.KindCase != Value.KindOneofCase.None;

Try / catch

try { json = formatter.Format(msg); } catch (InvalidOperationException ex) when (ex.Message.Contains("oneof")) { /* fill default kind and retry */ }

Prevention

When it happens

Trigger: Formatting a Value constructed with new Value() and never assigned any kind; calling ClearKind(); deserializing an empty/zero-length Value message and then formatting it.

Common situations: Default-initialized Value fields in hand-built messages; a Struct whose map values are empty Value instances; partial deserialization of truncated data.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

                if (!first)
                {
                    writer.Write(PropertySeparator);
                }
                WriteString(writer, key);
                writer.Write(NameValueSeparator);
                WriteStructFieldValue(writer, value);
                first = false;
            }
            writer.Write(first ? "}" : " }");
        }

        private void WriteStructFieldValue(TextWriter writer, IMessage message)
        {
            var specifiedField = message.Descriptor.Oneofs[0].Accessor.GetCaseFieldDescriptor(message);
            if (specifiedField == null)
            {
                throw new InvalidOperationException("Value message must contain a value for the oneof.");
            }

            object value = specifiedField.Accessor.GetValue(message);

            switch (specifiedField.FieldNumber)
            {
                case Value.BoolValueFieldNumber:
                case Value.StringValueFieldNumber:
                case Value.NumberValueFieldNumber:
                    WriteValue(writer, value);
                    return;
                case Value.StructValueFieldNumber:
                case Value.ListValueFieldNumber:
                    // Structs and ListValues are nested messages, and already well-known types.
                    var nestedMessage = (IMessage)specifiedField.Accessor.GetValue(message);
                    WriteWellKnownTypeValue(writer, nestedMessage.Descriptor, nestedMessage);
                    return;
                case Value.NullValueFieldNumber:

View on GitHub (pinned to 016f98412e)