dotnet/orleans · error · ArgumentException

The table version entry must have a membership version.

Error message

The table version entry must have a membership version.

What it means

Thrown by OrleansSiloInstanceManager.CreateBoundaryVersionEntries when the passed SiloInstanceTableEntry has a null MembershipVersion. Boundary version rows (TABLE_VERSION_ROW_MIN / _MAX) fence membership snapshots and must carry a version; a null means the caller constructed the entry incorrectly. ArgumentException names 'tableVersionEntry'.

Source

Thrown at src/Azure/Orleans.Clustering.AzureStorage/OrleansSiloInstanceManager.cs:99

                tableVersion.ToString(CultureInfo.InvariantCulture));
        }

        private SiloInstanceTableEntry CreateTableVersionEntry(string rowKey, string membershipVersion)
        {
            return new()
            {
                DeploymentId = DeploymentId,
                PartitionKey = DeploymentId,
                RowKey = rowKey,
                MembershipVersion = membershipVersion
            };
        }

        private (SiloInstanceTableEntry Min, SiloInstanceTableEntry Max) CreateBoundaryVersionEntries(
            SiloInstanceTableEntry tableVersionEntry)
        {
            var membershipVersion = tableVersionEntry.MembershipVersion
                ?? throw new ArgumentException("The table version entry must have a membership version.", nameof(tableVersionEntry));
            var min = CreateTableVersionEntry(SiloInstanceTableEntry.TABLE_VERSION_ROW_MIN, membershipVersion);
            var max = CreateTableVersionEntry(SiloInstanceTableEntry.TABLE_VERSION_ROW_MAX, membershipVersion);

            // Prevent older cleanup agents from treating boundary rows as defunct silo entries.
            min.Status = INSTANCE_STATUS_ACTIVE;
            max.Status = INSTANCE_STATUS_ACTIVE;
            return (min, max);
        }

        public void RegisterSiloInstance(SiloInstanceTableEntry entry)
        {
            entry.Status = INSTANCE_STATUS_CREATED;
            LogRegisterSiloInstance(entry);
            Task.WaitAll(new Task[] { storage.UpsertTableEntryAsync(entry) });
        }

        public Task<string> UnregisterSiloInstance(SiloInstanceTableEntry entry)
        {

View on GitHub (pinned to fca799fa70)

Solutions

  1. Ensure the tableVersionEntry passed in is built via CreateTableVersionEntry(int tableVersion), which sets MembershipVersion from a numeric version.
  2. If invoking CreateBoundaryVersionEntries indirectly, confirm the upstream version row read populated MembershipVersion (see error 153).
  3. Upgrade to a consistent Orleans version across the cluster so boundary-row construction agrees.
  4. Report an Orleans issue if this fires from released code paths with valid inputs.

Example fix

// before
var entry = new SiloInstanceTableEntry { RowKey = "Version" }; // MembershipVersion null

// after
var entry = manager.CreateTableVersionEntry(currentVersion); // sets MembershipVersion
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(tableVersionEntry.MembershipVersion))
    throw new InvalidOperationException("Version entry must carry MembershipVersion.");

Try / catch

try { var (min,max) = manager.CreateBoundaryVersionEntries(entry); }
catch (ArgumentException ex) when (ex.ParamName == nameof(tableVersionEntry))
{ /* build entry via CreateTableVersionEntry instead */ }

Prevention

When it happens

Trigger: Internal code path creating boundary entries from a tableVersionEntry whose MembershipVersion was not set. This is an Orleans-internal invariant; a throw here indicates a bug in version-row construction or a corrupt upstream read.

Common situations: Orleans version upgrade changing how version rows are built; a code path that constructs a version entry without setting MembershipVersion; partial deserialization of an entity missing the field.

Related errors


AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13). Data as JSON: /api/errors/e43ef309a7f94eb2. Report an issue: GitHub.