{"record":{"id":"1352d58149a5b8e9","repo":"pardeike/Harmony","slug":"no-parameter-found-at-index-argumentidx","errorCode":null,"errorMessage":"No parameter found at index {argumentIdx}","messagePattern":"No parameter found at index (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Harmony/Internal/MethodCreatorTools.cs","lineNumber":386,"sourceCode":"\t\t\t\t\tvar ldlocCode = paramType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc;\r\n\t\t\t\t\tcodes.Add(new CodeInstruction(ldlocCode, localBuilder));\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tint argumentIdx;\r\n\t\t\t\tif (injection.argumentMode == ArgumentMode.Original)\r\n\t\t\t\t{\r\n\t\t\t\t\targumentIdx = Array.IndexOf(originalParameterNames, paramRealName);\r\n\t\t\t\t\tif (argumentIdx == -1)\r\n\t\t\t\t\t\tthrow new Exception($\"Parameter \\\"{paramRealName}\\\" not found in method {original.FullDescription()}\");\r\n\t\t\t\t}\r\n\t\t\t\telse if (paramRealName.StartsWith(PARAM_INDEX_PREFIX, StringComparison.Ordinal))\r\n\t\t\t\t{\r\n\t\t\t\t\tvar val = paramRealName.Substring(PARAM_INDEX_PREFIX.Length);\r\n\t\t\t\t\tif (!int.TryParse(val, out argumentIdx))\r\n\t\t\t\t\t\tthrow new Exception($\"Parameter {paramRealName} does not contain a valid index\");\r\n\t\t\t\t\tif (argumentIdx < 0 || argumentIdx >= originalParameters.Length)\r\n\t\t\t\t\t\tthrow new Exception($\"No parameter found at index {argumentIdx}\");\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\targumentIdx = patch.GetArgumentIndex(originalParameterNames, injection.parameterInfo);\r\n\t\t\t\t\tif (argumentIdx == -1)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvar harmonyMethod = HarmonyMethodExtensions.GetMergedFromType(paramType);\r\n\t\t\t\t\t\tharmonyMethod.methodType ??= MethodType.Normal;\r\n\t\t\t\t\t\tvar delegateOriginal = harmonyMethod.GetOriginalMethod();\r\n\t\t\t\t\t\tif (delegateOriginal is MethodInfo methodInfo)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tvar delegateConstructor = paramType.GetConstructor([typeof(object), typeof(IntPtr)]);\r\n\t\t\t\t\t\t\tif (delegateConstructor is not null)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif (methodInfo.IsStatic)\r\n\t\t\t\t\t\t\t\t\tcodes.Add(Ldnull);\r\n\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t{\r","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/pardeike/Harmony/blob/e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c/Harmony/Internal/MethodCreatorTools.cs#L368-L404","documentation":"Harmony lets patch methods inject the n-th argument of the original method by naming a parameter like \"__0\" (the PARAM_INDEX_PREFIX). EmitCallParameter throws this when the parsed index is negative or >= the original method's parameter count, i.e. the patch asks for an argument slot the original method does not have. It protects the emitted IL from indexing past the end of the parameter array.","triggerScenarios":"Declaring a patch parameter named \"__N\" (or \"___idx\"-style index prefix) where N >= originalParameters.Length or N < 0, e.g. injecting \"__3\" into a 2-argument method, then patching and running EmitCallParameter during wrapper generation.","commonSituations":"The original method signature changed between library/game versions (an overload with fewer parameters is now bound), or the patch was copied from code targeting a different overload with more parameters.","solutions":["Count the original method's parameters and change the injected index parameter to a valid one (0..count-1).","Verify the target MethodBase resolved by Harmony is the overload you expect (use AccessTools.Method with explicit types).","If the index was copied from another patch, replace it with the matching named parameter instead of an index."],"exampleFix":"// before\nstatic void Postfix(ref int __3) { }\n// original has 2 params\n\n// after\nstatic void Postfix(ref int __1) { }","handlingStrategy":"validation","validationCode":"var paramCount = original.GetParameters().Length;\nforeach (var p in patchMethod.GetParameters())\n{\n    var name = p.Name;\n    if (name.StartsWith(\"__\") && int.TryParse(name.Substring(2), out var idx))\n        if (idx < 0 || idx >= paramCount)\n            throw new InvalidOperationException($\"{name} out of range for {original} ({paramCount} params)\");\n}","typeGuard":"static bool IsValidArgIndex(string paramName, int paramCount) =>\n    paramName.StartsWith(\"__\") && int.TryParse(paramName.Substring(2), out var i) && i >= 0 && i < paramCount;","tryCatchPattern":"try { harmony.Patch(original, prefix: prefix); }\ncatch (Exception ex) when (ex.Message.Contains(\"No parameter found at index\"))\n{ Logger.Error($\"Invalid __N injection on {original}: {ex.Message}\"); }","preventionTips":["Count original parameters before using __N-style injections.","Prefer named parameters or Harmony special names over numeric indexes.","Re-check indexes after updating the target library version."],"tags":["harmony","patch-parameters","argument-index"],"backgroundTag":"index-out-of-range","analyzedSha":"e7872dc17008bc0ca2b3de1f53fd4120dbd7a17c","analyzedAt":"2026-09-15T22:47:11.550Z","contentChangedAt":"2026-09-15T22:47:11.550Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}