{"record":{"id":"ad85c2e99311ca69","repo":"tursodatabase/turso","slug":"command-was-not-prepared","errorCode":null,"errorMessage":"Command was not prepared.","messagePattern":"Command was not prepared\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data/TursoCommand.cs","lineNumber":287,"sourceCode":"            : value.Equals(\"ON\", StringComparison.OrdinalIgnoreCase)\n              || value.Equals(\"TRUE\", StringComparison.OrdinalIgnoreCase)\n              || value.Equals(\"YES\", StringComparison.OrdinalIgnoreCase);\n    }\n\n    private DbDataReader Execute(CommandBehavior behavior = CommandBehavior.Default)\n    {\n        if (_connection is null)\n            throw new InvalidOperationException(\"Connection must be set before executing a command.\");\n\n        if (_connection.IsRemote)\n            return ExecuteRemoteAsync(behavior, CancellationToken.None).GetAwaiter().GetResult();\n\n        IDisposable? syncOperation = _connection.EnterSyncOperation();\n        try\n        {\n            PrepareCore();\n\n            var statement = _statement ?? throw new InvalidOperationException(\"Command was not prepared.\");\n            _statement = null;\n            try\n            {\n                var reader = new TursoDataReader(this, statement, behavior, syncOperation);\n                syncOperation = null;\n                return reader;\n            }\n            catch\n            {\n                statement.Dispose();\n                throw;\n            }\n        }\n        finally\n        {\n            syncOperation?.Dispose();\n        }\n    }","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/tursodatabase/turso/blob/c1e59287258d99b309e362a63f48822256e2f65f/bindings/dotnet/src/Turso.Data/TursoCommand.cs#L269-L305","documentation":"After Prepare() returns on the local path, Execute() expects the compiled TursoStatementHandle in _statement (TursoCommand.cs:276-278). 'Command was not prepared' means that invariant broke: most plausibly a TursoCommand subclass overrode Prepare() as a no-op without calling base, or the connection's remote client appeared between Execute's IsRemote check and Prepare's early remote return, leaving _statement null.","triggerScenarios":"Subclassing TursoCommand and overriding Prepare() without base.Prepare(); racing Open/Close of the connection from another thread while a local Execute is in flight.","commonSituations":"Exotic customization of command behavior; multithreaded sharing of one command/connection pair; not produced by ordinary sequential use of the shipped API.","solutions":["Do not override Prepare(); if you must, always call base.Prepare() first.","Use one command per thread and prefer creating commands per execution instead of sharing instances.","Avoid opening/closing the connection concurrently with execution on the same objects."],"exampleFix":"// before\npublic class MyCommand : TursoCommand\n{\n    public override void Prepare() { /* no base call */ }\n}\n\n// after\npublic class MyCommand : TursoCommand\n{\n    public override void Prepare() { base.Prepare(); /* extra work */ }\n}","handlingStrategy":"try-catch","validationCode":"if (cmd is not TursoCommand || cmd.Connection is not TursoConnection tc || tc.IsRemote)\n    throw new InvalidOperationException(\"Local prepared execution requires a bound local TursoConnection.\");","typeGuard":null,"tryCatchPattern":"try\n{\n    using var reader = cmd.ExecuteReader();\n}\ncatch (InvalidOperationException ex) when (ex.Message == \"Command was not prepared.\")\n{\n    // Invariant break: re-create the command from the connection and execute once more.\n    using var fresh = conn.CreateCommand();\n    fresh.CommandText = cmd.CommandText;\n    using var reader2 = fresh.ExecuteReader();\n}","preventionTips":["Never override Prepare() without calling base.Prepare().","Do not share a command across threads.","Keep Open/Close of the connection off threads that are executing commands."],"tags":["dotnet","ado-net","tursodb","prepare","invariant"],"backgroundTag":"statement-not-prepared","analyzedSha":"c1e59287258d99b309e362a63f48822256e2f65f","analyzedAt":"2026-08-31T11:17:35.598Z","contentChangedAt":"2026-08-31T11:17:35.598Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}