{"record":{"id":"16ab019927c6789b","repo":"JeffreySu/WeiXinMPSDK","slug":"botid","errorCode":null,"errorMessage":"BotID 不能为空。","messagePattern":"BotID 不能为空。","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/SmartRobot/SmartRobotWebSocketClient.cs","lineNumber":71,"sourceCode":"        /// <param name=\"endpoint\">WebSocket 服务地址，默认使用企业微信官方地址。</param>\n        public SmartRobotWebSocketClient(string endpoint = DefaultEndpoint)\n        {\n            _endpoint = new Uri(endpoint);\n            _socket = CreateSocket();\n        }\n\n        /// <summary>\n        /// 异步连接智能机器人 WebSocket 并订阅事件。\n        /// </summary>\n        /// <param name=\"botId\">智能机器人 ID。</param>\n        /// <param name=\"secret\">智能机器人 Secret。</param>\n        /// <param name=\"cancellationToken\">取消令牌。</param>\n        /// <returns>表示异步操作的任务。</returns>\n        public async Task ConnectAndSubscribeAsync(string botId, string secret,\n            CancellationToken cancellationToken = default)\n        {\n            ThrowIfDisposed();\n            _botId = string.IsNullOrWhiteSpace(botId) ? throw new ArgumentException(\"BotID 不能为空。\", nameof(botId)) : botId;\n            _secret = string.IsNullOrWhiteSpace(secret) ? throw new ArgumentException(\"Secret 不能为空。\", nameof(secret)) : secret;\n\n            if (_socket.State != WebSocketState.None)\n            {\n                _socket.Dispose();\n                _socket = CreateSocket();\n            }\n\n            await _socket.ConnectAsync(_endpoint, cancellationToken).ConfigureAwait(false);\n            await SendCommandAsync(\"aibot_subscribe\", CreateRequestId(), new\n            {\n                bot_id = _botId,\n                secret = _secret\n            }, cancellationToken).ConfigureAwait(false);\n        }\n\n        /// <summary>持续接收消息，直到取消、服务端关闭或网络断开。</summary>\n        /// <param name=\"cancellationToken\">取消令牌。</param>","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/SmartRobot/SmartRobotWebSocketClient.cs#L53-L89","documentation":"SmartRobotWebSocketClient.ConnectAndSubscribeAsync validates botId with string.IsNullOrWhiteSpace and throws ArgumentException(\"BotID 不能为空。\") when it is null, empty, or whitespace-only. The botId is required to establish the SmartRobot WebSocket subscription, and it is also stored on the client instance for reconnects.","triggerScenarios":"Calling ConnectAndSubscribeAsync(botId, secret) with botId null, \"\", or whitespace (e.g. \" \"), typically after ThrowIfDisposed has passed.","commonSituations":"Bot ID read from configuration that was never filled in, placeholder values left in appsettings, or botId coming from an upstream lookup that returned empty on first run.","solutions":["Supply a valid non-empty botId from your SmartRobot configuration.","Validate the botId at application startup before attempting connection.","If botId is fetched dynamically, handle the empty result before connecting."],"exampleFix":"// before\nawait client.ConnectAndSubscribeAsync(config.BotId, config.Secret); // BotId == null\n// after\nif (string.IsNullOrWhiteSpace(config.BotId))\n    throw new InvalidOperationException(\"配置缺少 BotID\");\nawait client.ConnectAndSubscribeAsync(config.BotId, config.Secret);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(botId)) throw new InvalidOperationException(\"SmartRobot BotID 未配置\");","typeGuard":null,"tryCatchPattern":"try { await client.ConnectAndSubscribeAsync(botId, secret, ct); } catch (ArgumentException ex) when (ex.ParamName == nameof(botId)) { logger.LogError(ex, \"BotID 为空，无法订阅\"); }","preventionTips":["Validate botId (and secret) right after loading configuration at startup.","Avoid whitespace-only placeholder values in config files.","Wrap connection setup in a factory method that enforces non-empty identifiers."],"tags":["argument","validation","websocket","smart-robot"],"backgroundTag":"empty-required-field","analyzedSha":"be573f6f94bdbf718dd5f6cdecb137fbc7ff651e","analyzedAt":"2026-09-12T10:01:50.733Z","contentChangedAt":"2026-09-12T10:01:50.733Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}