microsoft/autogen · error · RpcException
INVALID_ARGUMENT
INVALID_ARGUMENT
Error message
Grpc Client ID is required.
What it means
Thrown by GrpcGateway.RegisterAgentTypeAsync when the gRPC call does not carry a 'client-id' metadata header. The gateway identifies each worker by this header, so a registration without it cannot be attributed to any connection. It surfaces to the caller as an RpcException with StatusCode.InvalidArgument.
Source
Thrown at dotnet/src/Microsoft.AutoGen/RuntimeGateway.Grpc/Services/Grpc/GrpcGateway.cs:126
await connection.ResponseStream.WriteAsync(new Message { Request = request }, cancellationToken).ConfigureAwait(false);
var response = await completion.Task.WaitAsync(s_agentResponseTimeout);
response.RequestId = originalRequestId;
return response;
}
/// <summary>
/// Registers an agent type asynchronously.
/// </summary>
/// <param name="request">The register agent type request.</param>
/// <param name="context">The server call context.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the register agent type response.</returns>
public async ValueTask<RegisterAgentTypeResponse> RegisterAgentTypeAsync(RegisterAgentTypeRequest request, ServerCallContext context, CancellationToken cancellationToken = default)
{
try
{
var clientId = context.RequestHeaders.Get("client-id")?.Value ??
throw new RpcException(new Status(StatusCode.InvalidArgument, "Grpc Client ID is required."));
Func<ValueTask> registerLambda = async () =>
{
if (!_workers.TryGetValue(clientId, out var connection))
{
throw new RpcException(new Status(StatusCode.InvalidArgument, $"Grpc Worker Connection not found for ClientId {clientId}. Retry after you call OpenChannel() first."));
}
connection.AddSupportedType(request.Type);
_supportedAgentTypes.GetOrAdd(request.Type, _ => []).Add(connection);
await _gatewayRegistry.RegisterAgentTypeAsync(request, clientId, _reference).ConfigureAwait(true);
};
await InvokeOrDeferRegistrationAction(clientId, registerLambda).ConfigureAwait(true);
return new RegisterAgentTypeResponse { };
}
catch (Exception ex)View on GitHub (pinned to 027ecf0a37)
Solutions
- Attach the client-id header to the call: new Metadata { { "client-id", client.ClientId } } and pass it as headers when invoking RegisterAgentTypeAsync.
- Verify no client-side interceptor (logging, auth, retry) strips or renames custom metadata entries.
- If you use the shipped AutoGen .NET worker runtime, confirm you are on a version whose gateway and client agree on the 'client-id' header name (older builds used different identification schemes).
Example fix
// before
await client.RegisterAgentTypeAsync(new RegisterAgentTypeRequest { Type = "MyAgent" });
// after
var headers = new Metadata { { "client-id", clientId } };
await client.RegisterAgentTypeAsync(new RegisterAgentTypeRequest { Type = "MyAgent" }, headers); Defensive patterns
Strategy: validation
Validate before calling
// Before making the call, ensure metadata carries the header
var headers = new Metadata();
if (!headers.Any(h => h.Key == "client-id"))
{
headers.Add("client-id", clientId);
}
if (string.IsNullOrEmpty(headers.GetValue("client-id")?.Value))
throw new InvalidOperationException("client-id header must be set before RegisterAgentTypeAsync"); Try / catch
try { await client.RegisterAgentTypeAsync(request, headers); }
catch (RpcException ex) when (ex.StatusCode == StatusCode.InvalidArgument && ex.Status.Detail.Contains("Client ID is required"))
{
_logger.LogError("Missing client-id metadata; attaching and retrying once.");
headers.Add("client-id", clientId);
await client.RegisterAgentTypeAsync(request, headers);
} Prevention
- Centralize gRPC header construction in one client factory that always attaches client-id.
- Add an integration test asserting registration fails with a clear message when the header is absent.
- Log (not throw) at the client when client-id is empty before any gateway call.
When it happens
Trigger: Calling the RegisterAgentType RPC (or the AutoGen worker runtime's agent-type registration flow) without adding a 'client-id' entry to the request headers. The very first line of RegisterAgentTypeAsync reads context.RequestHeaders.Get("client-id") and throws when it is null.
Common situations: Custom worker implementations that build their own gRPC client and forget to attach metadata; SDK version upgrades that changed header names; proxies or interceptors that strip custom metadata; passing the id as part of the request body or message instead of headers.
Related errors
- Agent with name {agentId.Type} not found.
- Agent factory with type {type} already exists.
- Request message is missing a target. Message: '{request}'.
- Control message is missing a destination. Message: '{control
- Cannot convert control message to type {typeof(TMessage).Nam
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/23fb483e68352d22.
Report an issue: GitHub.