{"record":{"id":"133209b6ce7e54ea","repo":"tursodatabase/turso","slug":"batch-must-contain-at-least-one-command-133209","errorCode":null,"errorMessage":"Batch must contain at least one command.","messagePattern":"Batch must contain at least one command\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data/TursoRemoteClient.cs","lineNumber":85,"sourceCode":"\n        if (closeAfter)\n            request.Requests.Add(RemoteStreamRequest.Close());\n\n        var response = await SendPipelineAsync(request, commandTimeout, cancellationToken).ConfigureAwait(false);\n        UpdateSession(response, closeAfter);\n        return ExtractExecuteResult(response);\n    }\n\n    public async Task<IReadOnlyList<RemoteStatementResult>> ExecuteBatchAsync(\n        IReadOnlyList<TursoBatchCommand> commands,\n        int commandTimeout,\n        bool wantRows,\n        bool closeAfter,\n        CancellationToken cancellationToken)\n    {\n        ArgumentNullException.ThrowIfNull(commands);\n        if (commands.Count == 0)\n            throw new InvalidOperationException(\"Batch must contain at least one command.\");\n\n        var steps = new List<RemoteBatchStep>(commands.Count);\n        foreach (var command in commands)\n            steps.Add(new RemoteBatchStep { Statement = BuildStatement(command.CommandText, command.Parameters, wantRows) });\n\n        var request = new RemotePipelineRequest\n        {\n            Baton = _baton,\n            Requests =\n            [\n                RemoteStreamRequest.Batch(new RemoteBatch { Steps = steps }),\n            ],\n        };\n\n        if (closeAfter)\n            request.Requests.Add(RemoteStreamRequest.Close());\n\n        var response = await SendPipelineAsync(request, commandTimeout, cancellationToken).ConfigureAwait(false);","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data/TursoRemoteClient.cs#L67-L103","documentation":"TursoRemoteClient.ExecuteBatchAsync rejects an empty command list with this InvalidOperationException before building the remote pipeline request. An empty batch would produce a request with zero steps and no meaningful result, so it is refused up front rather than sent to the server. Note the separate ArgumentNullException for a null list — this variant is specifically for Count == 0.","triggerScenarios":"Calling ExecuteBatchAsync with an empty List<TursoBatchCommand>: a batch builder loop that filters out all statements, an API endpoint that accepts a list of operations and received none, or default/empty initialization followed by no Add calls.","commonSituations":"Bulk-sync endpoints where the incoming change set is empty; conditional batch construction ('if (condition) batch.Add(...)') where no condition matched; unit tests constructing batches programmatically.","solutions":["Guard the call: skip ExecuteBatchAsync when commands.Count == 0 and treat it as a no-op.","Log or assert when a caller builds an empty batch if emptiness indicates an upstream bug.","If batching user input, validate the request body rejects empty operation lists at the API boundary."],"exampleFix":"// before\nawait client.ExecuteBatchAsync(batch, timeout, wantRows, closeAfter, ct);\n\n// after\nif (batch.Count == 0) return [];\nawait client.ExecuteBatchAsync(batch, timeout, wantRows, closeAfter, ct);","handlingStrategy":"validation","validationCode":"if (commands is null || commands.Count == 0)\n    return Array.Empty<RemoteStatementResult>(); // empty batch is a no-op","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check Count at the boundary where batches are built (API handlers, sync loops).","Log empty batches if emptiness signals an upstream bug."],"tags":["csharp","dotnet","batching","validation","remote-client"],"backgroundTag":"empty-batch-rejected","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}