github/copilot-sdk · error · ArgumentException
Tool ' ' received non-object arguments, but its schema does…
Error message
Tool '{tool.Name}' received non-object arguments, but its schema does not define exactly one parameter or one required parameter. What it means
When a tool is called with non-object (e.g. string, array) arguments, the SDK must map that single value to exactly one tool parameter. If the tool's input schema does not define exactly one parameter — or exactly one required parameter — the SDK cannot decide where the value goes and throws ArgumentException.
Solutions
- Pass tool arguments as a JSON object keyed by the schema's property names.
- If bare values must be supported, make the tool schema define exactly one parameter (or exactly one required parameter).
- Instruct/constrain the model to emit object-form arguments matching the tool's inputSchema.
- Catch ArgumentException around tool dispatch and return a descriptive invalid-params error to the caller.
Example fix
// before
await session.CallToolAsync("search", JsonSerializer.SerializeToElement("cats"));
// after
await session.CallToolAsync("search", JsonSerializer.SerializeToElement(new { query = "cats" })); Defensive patterns
Strategy: validation
Validate before calling
if (args.ValueKind != JsonValueKind.Object &&
(tool.Schema.Properties?.Count != 1 || tool.Schema.Required?.Count != 1))
throw new ArgumentException($"Tool '{tool.Name}' requires object arguments"); Type guard
static bool ArgsFitTool(JsonElement args, Tool tool) =>
args.ValueKind == JsonValueKind.Object ||
(tool.Schema?.Properties?.Count == 1 && (tool.Schema.Required?.Count ?? 0) <= 1); Try / catch
try { await session.CallToolAsync(name, args); }
catch (ArgumentException ex) when (ex.Message.Contains("non-object arguments"))
{ return ToolError.InvalidParams(name, ex.Message); } Prevention
- Always pass tool arguments as a JSON object keyed by schema properties
- Design single-parameter schemas if positional/bare args must be supported
- Constrain the model to emit object-form tool arguments
When it happens
Trigger: Calling a tool whose inputSchema has 0 or 2+ parameters (or multiple required ones) while passing arguments that are not a JSON object, e.g. `CallTool("search", "my query")` instead of an object.
Common situations: LLMs emitting bare strings as tool arguments; wrapping a positional-style tool call against an MCP tool with multiple properties; hand-written clients using JSON-RPC positional params for tools with multi-property schemas.
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
- Cannot connect because TCP host or port are not available
- CLI process exited unexpectedly. stderr
- Client is not started. Call StartAsync first.
- Communication error with Copilot CLI
- ConnectionToken must be a non-empty string or null.
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/5d17a88323aa6547.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Session.cs:1084
{
if (requiredParameterName is not null)
{
requiredParameterName = null;
break;
}
requiredParameterName = requiredParameter.GetString();
}
if (requiredParameterName is not null &&
properties.TryGetProperty(requiredParameterName, out _))
{
return requiredParameterName;
}
}
}
throw new ArgumentException(
$"Tool '{tool.Name}' received non-object arguments, but its schema does not define exactly one parameter or one required parameter.");
}
}
private bool TryClaimExternalTool(string requestId, CancellationTokenSource cancellationSource)
=> ((ICollection<KeyValuePair<string, CancellationTokenSource>>)_pendingExternalTools)
.Remove(new(requestId, cancellationSource));
private void CancelExternalTool(string requestId)
{
if (!string.IsNullOrEmpty(requestId) && _pendingExternalTools.TryRemove(requestId, out var cancellationSource))
{
_ = Task.Run(() =>
{
try
{
cancellationSource.Cancel();
}View on GitHub (pinned to cd8cf15dc3)