{"record":{"id":"a2e50f513e9b0dd1","repo":"JeffreySu/WeiXinMPSDK","slug":"secret","errorCode":null,"errorMessage":"Secret 不能为空。","messagePattern":"Secret 不能为空。","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/SmartRobot/SmartRobotWebSocketClient.cs","lineNumber":72,"sourceCode":"        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>\n        /// <returns>表示异步操作的任务。</returns>","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/SmartRobot/SmartRobotWebSocketClient.cs#L54-L90","documentation":"SmartRobotWebSocketClient.ConnectAndSubscribeAsync validates secret with string.IsNullOrWhiteSpace and throws ArgumentException(\"Secret 不能为空。\") when the secret is null, empty, or whitespace. The secret authenticates the SmartRobot WebSocket handshake and is stored for automatic reconnects by RunWithReconnectAsync.","triggerScenarios":"Calling ConnectAndSubscribeAsync(botId, secret) with secret null, \"\", or whitespace-only, while botId is valid (or after botId validation passed).","commonSituations":"Secret not provisioned for the bot, secret stored in an environment variable that is unset in the deployment environment, or secrets rotated and the new value not yet injected into configuration.","solutions":["Provide the non-empty SmartRobot secret issued for your bot.","Check the environment/config source actually contains the secret in the deployment environment.","Validate secret before calling ConnectAndSubscribeAsync and surface a clear config error."],"exampleFix":"// before\nawait client.ConnectAndSubscribeAsync(botId, Environment.GetEnvironmentVariable(\"ROBOT_SECRET\")); // unset\n// after\nvar secret = Environment.GetEnvironmentVariable(\"ROBOT_SECRET\");\nif (string.IsNullOrWhiteSpace(secret))\n    throw new InvalidOperationException(\"ROBOT_SECRET 环境变量未设置\");\nawait client.ConnectAndSubscribeAsync(botId, secret);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(secret)) throw new InvalidOperationException(\"SmartRobot Secret 未配置\");","typeGuard":null,"tryCatchPattern":"try { await client.ConnectAndSubscribeAsync(botId, secret, ct); } catch (ArgumentException ex) when (ex.ParamName == nameof(secret)) { logger.LogError(ex, \"Secret 为空，无法建立 WebSocket 连接\"); }","preventionTips":["Verify secret-bearing environment variables are set in every deployment environment.","Add a startup readiness check for all required credentials.","Centralize secret retrieval in a provider that throws a clear config error when missing."],"tags":["argument","validation","websocket","credentials"],"backgroundTag":"missing-credentials","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"}