{"record":{"id":"b97b522d6c37bb43","repo":"JeffreySu/WeiXinMPSDK","slug":"operation","errorCode":null,"errorMessage":"operation","messagePattern":"operation","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.Work/Senparc.Weixin.Work/CommonAPIs/WorkApiClient.cs","lineNumber":49,"sourceCode":"            : this(AccessTokenContainer.BuildingKey(corpId, corpSecret))\n        {\n        }\n\n        public WorkApiClient(string appKey)\n        {\n            AppKey = !string.IsNullOrWhiteSpace(appKey)\n                ? appKey\n                : throw new ArgumentException(\"AppKey 不能为空。\", nameof(appKey));\n        }\n\n        public string AppKey { get; }\n\n        public T Execute<T>(Func<string, T> operation, bool retryInvalidCredential = true)\n            where T : WorkJsonResult, new()\n        {\n            if (operation == null)\n            {\n                throw new ArgumentNullException(nameof(operation));\n            }\n\n            return ApiHandlerWapperBase.TryCommonApiBase(\n                PlatformType.Work,\n                () => AppKey,\n                AccessTokenContainer.CheckRegistered,\n                AccessTokenContainer.GetTokenResult,\n                ApiHandlerWapper.InvalidCredentialValues,\n                operation,\n                AppKey,\n                retryInvalidCredential);\n        }\n\n        public Task<T> ExecuteAsync<T>(\n            Func<string, CancellationToken, Task<T>> operation,\n            CancellationToken cancellationToken = default,\n            bool retryInvalidCredential = true)\n            where T : WorkJsonResult, new()","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.Work/Senparc.Weixin.Work/CommonAPIs/WorkApiClient.cs#L31-L67","documentation":"WorkApiClient.Execute<T> throws ArgumentNullException with the parameter name \"operation\" when the Func<string,T> delegate passed to it is null. The delegate is the actual API call the client should run through the access-token retry wrapper (ApiHandlerWapperBase.TryCommonApiBase), so a null delegate means there is nothing to execute. This is a fast-fail guard to surface caller bugs immediately instead of a NullReferenceException deeper inside the retry pipeline.","triggerScenarios":"Calling WorkApiClient.Execute<T>(null) — e.g. building the delegate conditionally and passing null, or forwarding a null result from another factory method.","commonSituations":"Refactors where a lambda was accidentally removed or replaced by a variable that is null; helper wrappers that build the operation dynamically and return null when no API method matched.","solutions":["Pass a non-null Func<string, T> delegate, e.g. client.Execute(url => ApiCall(url));","If the delegate is built conditionally, check for null before calling Execute or throw a descriptive exception in the factory.","Inspect the call site so the lambda is not lost when assigning to a local variable."],"exampleFix":"// before\nFunc<string, MyJsonResult> op = BuildOperation();\nvar result = client.Execute(op); // op may be null\n// after\nvar op = BuildOperation() ?? throw new InvalidOperationException(\"No API operation was built.\");\nvar result = client.Execute(op);","handlingStrategy":"validation","validationCode":"if (operation == null) throw new InvalidOperationException(\"API operation delegate must be supplied before calling WorkApiClient.Execute.\");\nvar result = client.Execute(operation);","typeGuard":"bool IsCallable<T>(Func<string, T> op) where T : WorkJsonResult, new() => op is not null;","tryCatchPattern":"try\n{\n    var result = client.Execute(op);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"operation\")\n{\n    log.LogError(\"WorkApiClient.Execute received a null operation delegate.\");\n}","preventionTips":["Never store delegates in nullable variables before passing them to Execute.","Have delegate factories throw instead of returning null.","Code-review any wrapper around WorkApiClient for null-forgiving patterns."],"tags":["argument-null","api-client","work-weixin"],"backgroundTag":"null-argument","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"}