dotnet/orleans · error · ArgumentNullException

Value cannot be null. (Parameter 'createClientCallback')

Error message

Value cannot be null. (Parameter 'createClientCallback')

What it means

Thrown by AzureStorageOperationOptions.ConfigureTableServiceClient(Func<Task<TableServiceClient>>) when the supplied callback is null. This overload is marked [Obsolete] — the supported way is to assign the TableServiceClient property directly. The guard simply prevents a null CreateClient from being stored, which would later fail at Validate().

Source

Thrown at src/Azure/Shared/Storage/AzureStorageOperationOptions.cs:93

            SetTableServiceClient(connectionString);
        }

        /// <summary>
        /// Configures the <see cref="TableServiceClient"/> using an authenticated service URI.
        /// </summary>
        [Obsolete($"Set the {nameof(TableServiceClient)} property directly.")]
        public void ConfigureTableServiceClient(Uri serviceUri)
        {
            SetTableServiceClient(serviceUri);
        }

        /// <summary>
        /// Configures the <see cref="TableServiceClient"/> using the provided callback.
        /// </summary>
        [Obsolete($"Set the {nameof(TableServiceClient)} property directly.")]
        public void ConfigureTableServiceClient(Func<Task<TableServiceClient>> createClientCallback)
        {
            CreateClient = createClientCallback ?? throw new ArgumentNullException(nameof(createClientCallback));
        }

        /// <summary>
        /// Configures the <see cref="TableServiceClient"/> using an authenticated service URI and a <see cref="Azure.Core.TokenCredential"/>.
        /// </summary>
        [Obsolete($"Set the {nameof(TableServiceClient)} property directly.")]
        public void ConfigureTableServiceClient(Uri serviceUri, TokenCredential tokenCredential)
        {
            SetTableServiceClient(serviceUri, tokenCredential);
        }

        /// <summary>
        /// Configures the <see cref="TableServiceClient"/> using an authenticated service URI and a <see cref="Azure.AzureSasCredential"/>.
        /// </summary>
        [Obsolete($"Set the {nameof(TableServiceClient)} property directly.")]
        public void ConfigureTableServiceClient(Uri serviceUri, AzureSasCredential azureSasCredential)
        {
            SetTableServiceClient(serviceUri, azureSasCredential);

View on GitHub (pinned to fca799fa70)

Solutions

  1. Stop using the obsolete ConfigureTableServiceClient callback overload; set options.TableServiceClient directly.
  2. If you must keep the callback, supply a non-null Func<Task<TableServiceClient>>.
  3. Add a null check / IDE diagnostic around the callback expression so the failure is local.

Example fix

// before (obsolete, throws on null)
options.ConfigureTableServiceClient(maybeCallback);
// after (recommended)
options.TableServiceClient = new TableServiceClient(connectionString);
Defensive patterns

Strategy: validation

Validate before calling

if (createClientCallback is null) throw new ArgumentNullException(nameof(createClientCallback));
options.ConfigureTableServiceClient(createClientCallback);

Type guard

static bool IsCallbackConfigured(Func<Task<TableServiceClient>>? cb) => cb is not null;

Try / catch

catch (ArgumentNullException ex) when (ex.ParamName == "createClientCallback") { /* supply a real callback or set TableServiceClient directly */ }

Prevention

When it happens

Trigger: Calling options.ConfigureTableServiceClient((Func<Task<TableServiceClient>>)null) or passing a variable that was never assigned. Also appears during migration to the SDK-style client where old wiring code passes null unintentionally.

Common situations: Migrating off the obsolete Configure* methods; DI configuration that conditionally builds a callback and falls through to null; copy-paste of a sample that omitted the callback.

Related errors


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