XINCGer/Unity3DTraining · error · InvalidOperationException

Struct fields cannot have an empty key or a null value.

Error message

Struct fields cannot have an empty key or a null value.

What it means

JsonFormatter.WriteStruct throws InvalidOperationException when a google.protobuf.Struct's fields map contains an empty string key or a null value entry. Struct is defined to have non-empty keys and non-null Value messages; the formatter enforces this invariant.

Solutions

  1. Remove null-valued and empty-key entries before formatting, or represent nulls as Value.ForNull()
  2. Validate the source dictionary before converting it into a Struct
  3. Use the generated Struct/Value APIs (Value.ForString etc.) instead of raw map mutation
  4. Sanitize third-party JSON before packing into a Struct

Example fix

// before
structMsg.Fields[""] = null;
// after
structMsg.Fields["key"] = Value.ForNull(); // non-empty key; use Value.ForNull for JSON null
Defensive patterns

Strategy: validation

Validate before calling

bool structIsValid = structMsg.Fields.All(kv => !string.IsNullOrEmpty(kv.Key) && kv.Value != null);

Type guard

static bool IsValidStructEntry(KeyValuePair<string, Value> e) => !string.IsNullOrEmpty(e.Key) && e.Value != null;

Try / catch

try { json = formatter.Format(structMsg); } catch (InvalidOperationException ex) when (ex.Message.Contains("Struct fields")) { /* sanitize struct and retry */ }

Prevention

When it happens

Trigger: Manually mutating the Struct's fields dictionary (Struct.Fields[key] = null, or adding ""); deserializing malformed data into a Struct and then formatting it; reflection-based code inserting null Values.

Common situations: Hand-constructing Struct values from user dictionaries that contain empty keys or nulls; bridges from JSON.NET/other serializers that preserve null entries; corrupted payloads.

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/b449f1c1b95f3a41. Report an issue: GitHub.

Appendix: source

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

            writer.Write(NameValueSeparator);
            writer.Write('"');
            writer.Write(data.ToBase64());
            writer.Write('"');
            writer.Write(" }");
        }

        private void WriteStruct(TextWriter writer, IMessage message)
        {
            writer.Write("{ ");
            IDictionary fields = (IDictionary)message.Descriptor.Fields[Struct.FieldsFieldNumber].Accessor.GetValue(message);
            bool first = true;
            foreach (DictionaryEntry entry in fields)
            {
                string key = (string)entry.Key;
                IMessage value = (IMessage)entry.Value;
                if (string.IsNullOrEmpty(key) || value == null)
                {
                    throw new InvalidOperationException("Struct fields cannot have an empty key or a null value.");
                }

                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)

View on GitHub (pinned to 016f98412e)