{"record":{"id":"e2a93b61c1e0f4b5","repo":"tursodatabase/turso","slug":"batch-command-text-must-contain-a-sql-statement","errorCode":null,"errorMessage":"Batch command text must contain a SQL statement.","messagePattern":"Batch command text must contain a SQL statement\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data.Sqlite/SqliteBatch.cs","lineNumber":303,"sourceCode":"        {\n            Timeout = Timeout,\n            Transaction = _transaction?.ManagedTransaction,\n        };\n        var statements = new List<ManagedSqliteStatement>();\n        var managedCommands = new List<global::Turso.TursoBatchCommand>();\n        var mappings = new List<BatchCommandMapping>(_batchCommands.Count);\n        try\n        {\n            foreach (var batchCommand in _batchCommands.Items)\n            {\n                using var command = new SqliteCommand(batchCommand.CommandText, connection, _transaction);\n                foreach (SqliteParameter parameter in batchCommand.Parameters)\n                    command.Parameters.Add(parameter);\n                command.ValidateManagedParameterValues();\n\n                var commandStatements = ManagedSqliteStatementParser.Parse(batchCommand.CommandText);\n                if (commandStatements.Count == 0)\n                    throw new InvalidOperationException(\"Batch command text must contain a SQL statement.\");\n                if (commandStatements.Any(static statement => statement.IsTransactionControl))\n                {\n                    throw new InvalidOperationException(\n                        \"Transaction-control SQL is not supported in a SqliteBatch. \"\n                        + \"Use SqliteConnection.BeginTransaction and SqliteTransaction instead.\");\n                }\n                if (connection.IsReadOnly\n                    && commandStatements.Any(SqliteCommand.IsWriteStatement))\n                {\n                    throw new SqliteException(\n                        Properties.Resources.SqliteNativeError(8, \"attempt to write a readonly database\"),\n                        8);\n                }\n\n                var firstManagedIndex = managedCommands.Count;\n                foreach (var statement in commandStatements)\n                {\n                    string sql;","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data.Sqlite/SqliteBatch.cs#L285-L321","documentation":"Before executing, BuildBatch parses each batch command's CommandText with ManagedSqliteStatementParser. If parsing yields zero statements (empty or whitespace/comment-only text), an InvalidOperationException is thrown because a batch entry must contain at least one SQL statement.","triggerScenarios":"Adding a SqliteBatch command whose CommandText is null, empty, whitespace, or only comments (e.g. \"-- done\"), then calling ExecuteReader/ExecuteBatch.","commonSituations":"Building command text dynamically from templates where a variable evaluates to empty string; conditional code that skips filling in SQL; trailing comment-only cleanup text.","solutions":["Set CommandText to non-empty SQL before executing the batch","Guard: skip adding the batch command when string.IsNullOrWhiteSpace(sql)","Trim/validate all batch command texts during construction"],"exampleFix":"// before\nbatch.Commands.Add(new SqliteBatchCommand { CommandText = maybeEmptySql });\nawait batch.ExecuteReaderAsync();\n// after\nif (!string.IsNullOrWhiteSpace(maybeEmptySql))\n    batch.Commands.Add(new SqliteBatchCommand { CommandText = maybeEmptySql });","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(cmd.CommandText))\n    throw new InvalidOperationException(\"Batch command text is empty\");","typeGuard":"static bool HasSql(SqliteBatchCommand c) => !string.IsNullOrWhiteSpace(c.CommandText);","tryCatchPattern":"try { await batch.ExecuteReaderAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"must contain a SQL statement\")) { /* skip/skip-empty command */ }","preventionTips":["Validate all CommandTexts when building the batch","Never add commands with template placeholders that may resolve to empty","Trim and assert non-empty SQL in your data-access helpers"],"tags":["dotnet","batch","validation","empty-input"],"backgroundTag":"empty-required-field","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-09-06T07:15:26.990Z","contentChangedAt":"2026-09-06T07:15:26.990Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}