{"record":{"id":"63819431de865108","repo":"microsoft/semantic-kernel","slug":"a-message-targeting-function-message-functionnam","errorCode":null,"errorMessage":"A message targeting function '{message.FunctionName}' has resulted in a function named '{invocableFunctions.First()}' becoming invocable. Are the function names configured correctly?","messagePattern":"A message targeting function '(.+?)' has resulted in a function named '(.+?)' becoming invocable\\. Are the function names configured correctly\\?","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Experimental/Process.LocalRuntime/LocalStep.cs","lineNumber":225,"sourceCode":"        }\n\n        // Add the message values to the inputs for the function\n        this.AssignStepFunctionParameterValues(message);\n\n        // If we're still waiting for inputs on all of our functions then don't do anything.\n        List<string> invocableFunctions = this._inputs.Where(i => i.Value != null && i.Value.All(v => v.Value != null)).Select(i => i.Key).ToList();\n        var missingKeys = this._inputs.Where(i => i.Value is null || i.Value.Any(v => v.Value is null));\n\n        if (invocableFunctions.Count == 0)\n        {\n            string missingKeysLog() => string.Join(\", \", missingKeys.Select(k => $\"{k.Key}: {string.Join(\", \", k.Value?.Where(v => v.Value == null).Select(v => v.Key) ?? [])}\"));\n            this._logger.LogDebug(\"No invocable functions, missing keys: {MissingKeys}\", missingKeysLog());\n            return;\n        }\n\n        // A message can only target one function and should not result in a different function being invoked.\n        var targetFunction = invocableFunctions.FirstOrDefault((name) => name == message.FunctionName) ??\n            throw new InvalidOperationException($\"A message targeting function '{message.FunctionName}' has resulted in a function named '{invocableFunctions.First()}' becoming invocable. Are the function names configured correctly?\");\n\n        this._logger.LogDebug(\"Step with Id `{StepId}` received all required input for function [{TargetFunction}] and is executing.\", this.Name, targetFunction);\n\n        // Concat all the inputs and run the function\n        KernelArguments arguments = new(this._inputs[targetFunction]!);\n        if (!this._functions.TryGetValue(targetFunction, out KernelFunction? function) || function == null)\n        {\n            throw new ArgumentException($\"Function {targetFunction} not found in plugin {this.Name}\");\n        }\n\n        // Invoke the function, catching all exceptions that it may throw, and then post the appropriate event.\n#pragma warning disable CA1031 // Do not catch general exception types\n        try\n        {\n            // TODO: Process edges for the OnStepEnter event: This feels like a good use for filters in the non-declarative version\n\n            FunctionResult invokeResult = await this.InvokeFunction(function, this._kernel, arguments).ConfigureAwait(false);\n            this.EmitEvent(","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Experimental/Process.LocalRuntime/LocalStep.cs#L207-L243","documentation":"Thrown as InvalidOperationException by LocalStep.HandleMessageAsync when a message targets function X, but after assigning its inputs, a different function Y becomes fully invocable (all its required parameters are present). The framework enforces that a message for one function should not inadvertently complete the inputs of another function, which indicates the function names on edges do not match the step's actual function names.","triggerScenarios":"A message with FunctionName='A' is processed, and after AssignStepFunctionParameterValues merges the values, the invocableFunctions list contains only 'B' (not 'A'). The FirstOrDefault match on message.FunctionName fails, triggering the throw.","commonSituations":"An edge targets function 'ProcessData' but the step's method is named 'HandleData'; renaming a step's [KernelFunction] method without updating edge targets; case mismatch in function names; multiple functions sharing parameter names so that a message for one fills another's inputs.","solutions":["Ensure the FunctionName on every edge's KernelProcessFunctionTarget matches a [KernelFunction] method name on the target step exactly.","Check for case-sensitivity issues in function names (e.g., 'process' vs 'Process').","If two functions share parameter names, rename parameters or functions to avoid ambiguity in input channel resolution.","Inspect the FindInputChannels logic to verify parameter-to-function mapping is unambiguous."],"exampleFix":"// before - edge targets 'ProcessData' but step method is 'HandleData'\nedge.OutputTarget = new KernelProcessFunctionTarget { FunctionName = \"ProcessData\" };\n[KernelFunction] public void HandleData(string input) { }\n// after - names match\nedge.OutputTarget = new KernelProcessFunctionTarget { FunctionName = \"HandleData\" };","handlingStrategy":"validation","validationCode":"// Validate that edge FunctionNames match actual KernelFunction method names on the step type\nvar functionNames = typeof(MyStep).GetMethods()\n    .Where(m => m.GetCustomAttribute<KernelFunctionAttribute>() != null)\n    .Select(m => m.Name).ToHashSet();\nforeach (var edgeList in process.Edges.Values)\n{\n    foreach (var edge in edgeList)\n    {\n        if (edge.OutputTarget is KernelProcessFunctionTarget ft && ft.StepId == myStepId)\n        {\n            if (!functionNames.Contains(ft.FunctionName)) { /* configuration error */ }\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep edge FunctionName values in sync with [KernelFunction] method names on step classes.","Run a validation pass that reflects on step types and checks edge targets before StartAsync.","Avoid giving two functions overlapping parameter names that could cause cross-invocation."],"tags":["process-framework","step","function-routing","configuration","function-name-mismatch"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}