{"record":{"id":"5970464872dbbd40","repo":"github/copilot-sdk","slug":"ffiruntimehost-has-not-been-started","errorCode":null,"errorMessage":"FfiRuntimeHost has not been started.","messagePattern":"FfiRuntimeHost has not been started\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/FfiRuntimeHost.cs","lineNumber":68,"sourceCode":"    private uint _serverId;\n    private uint _connectionId;\n    private bool _disposed;\n\n    private FfiRuntimeHost(string libraryPath, string? cliEntrypoint, IReadOnlyDictionary<string, string>? environment, IReadOnlyList<string> args, ILogger logger)\n    {\n        _libraryPath = libraryPath;\n        _cliEntrypoint = cliEntrypoint;\n        _environment = environment;\n        _args = args;\n        _logger = logger;\n    }\n\n    /// <summary>The stream JSON-RPC reads server→client frames from.</summary>\n    public Stream ReceiveStream => _receiveStream;\n\n    /// <summary>The stream JSON-RPC writes client→server frames to.</summary>\n    public Stream SendStream => _sendStream\n        ?? throw new InvalidOperationException(\"FfiRuntimeHost has not been started.\");\n\n    /// <summary>\n    /// Loads the runtime cdylib and prepares the FFI host.\n    /// </summary>\n    public static FfiRuntimeHost Create(string libraryPath, string? cliEntrypoint, IReadOnlyDictionary<string, string>? environment, IReadOnlyList<string> args, ILogger logger)\n    {\n        var fullLibraryPath = Path.GetFullPath(libraryPath);\n        if (!File.Exists(fullLibraryPath))\n        {\n            throw new InvalidOperationException($\"FFI runtime library not found at '{fullLibraryPath}'.\");\n        }\n        PrepareNativeLibrary(fullLibraryPath);\n        return new FfiRuntimeHost(\n            fullLibraryPath,\n            cliEntrypoint is null ? null : Path.GetFullPath(cliEntrypoint),\n            environment,\n            args,\n            logger);","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/dotnet/src/FfiRuntimeHost.cs#L50-L86","documentation":"FfiRuntimeHost exposes SendStream only after StartAsync has initialized the client→server frame pipe. Accessing SendStream before the host is started throws this InvalidOperationException because the stream is still null.","triggerScenarios":"Reading the SendStream property before calling StartAsync, or after a failed StartAsync that never assigned the stream; accessing it from another thread while StartAsync is still running.","commonSituations":"Consumers wire up JSON-RPC transport at construction time instead of after start; initialization failed earlier and the null stream is hit downstream; ordering bug where the transport setup races StartAsync.","solutions":["Call (and await) StartAsync before accessing SendStream or wiring the JSON-RPC transport","Check whether a prior StartAsync call failed and handle/retry initialization","Sequence transport setup in the StartAsync continuation rather than the constructor"],"exampleFix":"// before\nvar host = FfiRuntimeHost.Create(libPath, null, null, args, logger);\nvar rpc = new JsonRpc(host.SendStream, host.ReceiveStream); // throws\n// after\nvar host = FfiRuntimeHost.Create(libPath, null, null, args, logger);\nawait host.StartAsync();\nvar rpc = new JsonRpc(host.SendStream, host.ReceiveStream);","handlingStrategy":"validation","validationCode":"if (!host.Started) await host.StartAsync();\nvar send = host.SendStream; // safe now","typeGuard":"bool HostReady(FfiRuntimeHost host) => host.Started; // SendStream non-null only after StartAsync","tryCatchPattern":"Stream send;\ntry { send = host.SendStream; }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"has not been started\")) { await host.StartAsync(); send = host.SendStream; }","preventionTips":["Always call StartAsync before accessing SendStream","Wire JSON-RPC transport in the post-start continuation","Handle failed StartAsync before downstream access"],"tags":["ffi","initialization","dotnet"],"backgroundTag":"missing-required-config-field","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}