{"record":{"id":"16c369b7c0778523","repo":"kubernetes/kops","slug":"found-multiple-render-methods-that-could-be-involv","errorCode":null,"errorMessage":"found multiple Render methods that could be involved on %T","messagePattern":"found multiple Render methods that could be involved on %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/context.go","lineNumber":254,"sourceCode":"\t\t\t}\n\t\t\tif typeContextPtr.ConvertibleTo(arg) {\n\t\t\t\targs = append(args, reflect.ValueOf(c))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif targetType.ConvertibleTo(arg) {\n\t\t\t\targs = append(args, reflect.ValueOf(c.Target))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch = false\n\t\t\tbreak\n\t\t}\n\t\tif match {\n\t\t\tif renderer.IsValid() {\n\t\t\t\tif candidate.name == \"Render\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif rendererName != \"Render\" {\n\t\t\t\t\treturn fmt.Errorf(\"found multiple Render methods that could be involved on %T\", e)\n\t\t\t\t}\n\t\t\t}\n\t\t\trendererName = candidate.name\n\t\t\trenderer = candidate.method\n\t\t\trendererArgs = args\n\t\t}\n\n\t}\n\tif !renderer.IsValid() {\n\t\treturn fmt.Errorf(\"could not find Render method on type %T (target %T)\", e, c.Target)\n\t}\n\trendererArgs = append(rendererArgs, reflect.ValueOf(a))\n\trendererArgs = append(rendererArgs, reflect.ValueOf(e))\n\trendererArgs = append(rendererArgs, reflect.ValueOf(changes))\n\tklog.V(11).Infof(\"Calling method %s on %T\", rendererName, e)\n\trv := renderer.Call(rendererArgs)\n\tvar rvErr error\n\tif !rv[0].IsNil() {","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/context.go#L236-L272","documentation":"Render uses reflection to find exactly one renderer method (Render, RenderAWS, RenderGCE, etc.) whose signature is compatible with the task and target. If two or more candidate methods match and neither is the generic Render, the dispatch is ambiguous — kops refuses to guess and returns this error naming the task type %T.","triggerScenarios":"A Task implementation defines multiple cloud-specific renderers (e.g. both RenderAWS and RenderGCE) whose parameter types are all convertible to/from the current target type, so reflection matches both; usually caused by method signatures that are too generic (accepting interfaces/targets convertible from everything).","commonSituations":"Custom task written by a kops contributor with overly broad Render<X> signatures (e.g. taking `interface{}` or a common Target type); refactoring that loosened a method's parameter type; adding a new RenderX without narrowing its argument types.","solutions":["Narrow the renderer method's parameter types (use the concrete aws.API/target type) so only one candidate matches.","Implement the generic `Render(c *Context, a, e, changes Task)` method only, removing per-cloud renderers, if one implementation suffices.","Add the specific Render<Provider> only for clouds the task truly supports and ensure other methods' first non-task parameter is not convertible from the current target."],"exampleFix":"// before — ambiguous, both match\ntfunc (t *myTask) RenderAWS(c *fi.Context, a, e, changes *myTask) error\nfunc (t *myTask) RenderGCE(c interface{}, a, e, changes *myTask) error\n// after — only the applicable provider's renderer has a matching signature\nfunc (t *myTask) RenderAWS(c *fi.Context, a, e, changes *myTask) error\nfunc (t *myTask) RenderGCE(g *gce.GCECloud, a, e, changes *myTask) error","handlingStrategy":"validation","validationCode":"// build-time check: exactly one renderer signature must accept the target type\n// keep Render<X> first param a concrete provider cloud/target type","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give each cloud-specific renderer a concrete provider-specific first parameter type.","Implement only the generic Render method when one implementation suffices.","After refactoring task method signatures, run unit tests exercising Context.Render dispatch."],"tags":["reflection","task-engine","render-dispatch","developer-error"],"backgroundTag":"ambiguous-render-method","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}