XINCGer/Unity3DTraining · error · ArgumentException

Not all required properties/methods available

Error message

Not all required properties/methods available

What it means

SingleFieldAccessor requires the wrapped CLR property to be writable so it can bind a setter delegate (and the base class requires it readable). If PropertyInfo.CanWrite is false the constructor throws ArgumentException. It reflects a mismatch between the property being wrapped and a real generated protobuf single (non-repeated) field.

Solutions

  1. Wrap only genuine generated single-field properties, which have public getters and setters.
  2. If the class is hand-written, add a public setter to the property.
  3. Use RepeatedFieldAccessor/MapFieldAccessor for repeated or map fields instead of SingleFieldAccessor.

Example fix

// before
public string Name => name_; // get-only, throws
// after
public string Name { get { return name_; } set { name_ = value ?? ""; } }
Defensive patterns

Strategy: validation

Validate before calling

if (prop == null || !prop.CanRead || !prop.CanWrite)
    throw new InvalidOperationException($"Property {prop?.Name} must be readable and writable for SingleFieldAccessor");

Type guard

bool IsWritableField(PropertyInfo p) => p != null && p.CanRead && p.CanWrite;

Try / catch

try { accessor = new SingleFieldAccessor(prop, desc); } catch (ArgumentException ex) { log.Error($"Field accessor requires writable property: {ex.Message}"); throw; }

Prevention

When it happens

Trigger: Constructing SingleFieldAccessor (directly or via FieldDescriptor accessor creation) with a get-only property — e.g. read-only computed properties, map/repeated fields exposed read-only, or properties from a hand-written IMessage implementation lacking setters.

Common situations: Wrapping properties of read-only view types or protos generated with settings that expose collections without setters, in custom reflection/serialization tooling.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/Reflection/SingleFieldAccessor.cs:56

{
    /// <summary>
    /// Accessor for single fields.
    /// </summary>
    internal sealed class SingleFieldAccessor : FieldAccessorBase
    {
        // All the work here is actually done in the constructor - it creates the appropriate delegates.
        // There are various cases to consider, based on the property type (message, string/bytes, or "genuine" primitive)
        // and proto2 vs proto3 for non-message types, as proto3 doesn't support "full" presence detection or default
        // values.

        private readonly Action<IMessage, object> setValueDelegate;
        private readonly Action<IMessage> clearDelegate;

        internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
        {
            if (!property.CanWrite)
            {
                throw new ArgumentException("Not all required properties/methods available");
            }
            setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod());

            var clrType = property.PropertyType;

            // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
            object defaultValue =
                descriptor.FieldType == FieldType.Message ? null
                : clrType == typeof(string) ? ""
                : clrType == typeof(ByteString) ? ByteString.Empty
                : Activator.CreateInstance(clrType);
            clearDelegate = message => SetValue(message, defaultValue);
        }

        public override void Clear(IMessage message)
        {
            clearDelegate(message);
        }

View on GitHub (pinned to 016f98412e)