pardeike/Harmony · error · Exception
Parameter does not contain a valid index
Error message
Parameter {paramRealName} does not contain a valid index What it means
A patch parameter uses index-based argument binding (name starting with PARAM_INDEX_PREFIX, e.g. `__0`). The text after the prefix must parse as an int; Harmony throws this Exception when int.TryParse fails. It indicates a malformed index-based parameter name in the patch signature.
Solutions
- Use a plain decimal index after the prefix, e.g. `__0`, `__1`.
- Bind by original parameter name instead of index to avoid format issues.
- Sanitize generated patch parameter names to ensure the suffix after the prefix is digits only.
Example fix
// before
static void Postfix(int __first) { ... }
// after
static void Postfix(int __0) { ... } Defensive patterns
Strategy: validation
Validate before calling
if (name.StartsWith("__") && !int.TryParse(name.Substring(2), out _))
throw new ArgumentException($"Bad index parameter name: {name}"); Type guard
bool IsWellFormedIndexParam(string name) =>
name.StartsWith("__") && int.TryParse(name.Substring(2), out var i) && i >= 0; Try / catch
try { harmony.Patch(original, postfix: new HarmonyMethod(fix)); }
catch (Exception ex) when (ex.Message.Contains("does not contain a valid index")) { log.Error(ex); } Prevention
- Only digits after the index prefix
- Validate generated patch signatures in unit tests
- Prefer name-based binding when indexes are unclear
When it happens
Trigger: Writing an index-prefixed patch parameter whose suffix is not a valid integer, e.g. `__abc`, `__0x1`, or a name where the prefix collides with a user parameter name that happens to start with the prefix.
Common situations: Typos in hand-written patch signatures; code generation emitting malformed names; accidentally prefixing a normal parameter name with the index marker.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- No field found at given index in class
- No such field defined in class
- Cannot get result from void method
- Parameter " " not found in method
- The type must declare an empty constructor (the constructor…
AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15).
Data as JSON: /api/errors/0039ad430c7b7111.
Report an issue: GitHub.
Appendix: source
Thrown at Harmony/Internal/MethodCreatorTools.cs:384
if (injection.argumentMode != ArgumentMode.Original && config.localVariables.TryGetValue(paramRealName, out var localBuilder))
{
var ldlocCode = paramType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc;
codes.Add(new CodeInstruction(ldlocCode, localBuilder));
continue;
}
int argumentIdx;
if (injection.argumentMode == ArgumentMode.Original)
{
argumentIdx = Array.IndexOf(originalParameterNames, paramRealName);
if (argumentIdx == -1)
throw new Exception($"Parameter \"{paramRealName}\" not found in method {original.FullDescription()}");
}
else if (paramRealName.StartsWith(PARAM_INDEX_PREFIX, StringComparison.Ordinal))
{
var val = paramRealName.Substring(PARAM_INDEX_PREFIX.Length);
if (!int.TryParse(val, out argumentIdx))
throw new Exception($"Parameter {paramRealName} does not contain a valid index");
if (argumentIdx < 0 || argumentIdx >= originalParameters.Length)
throw new Exception($"No parameter found at index {argumentIdx}");
}
else
{
argumentIdx = patch.GetArgumentIndex(originalParameterNames, injection.parameterInfo);
if (argumentIdx == -1)
{
var harmonyMethod = HarmonyMethodExtensions.GetMergedFromType(paramType);
harmonyMethod.methodType ??= MethodType.Normal;
var delegateOriginal = harmonyMethod.GetOriginalMethod();
if (delegateOriginal is MethodInfo methodInfo)
{
var delegateConstructor = paramType.GetConstructor([typeof(object), typeof(IntPtr)]);
if (delegateConstructor is not null)
{
if (methodInfo.IsStatic)
codes.Add(Ldnull);
View on GitHub (pinned to e7872dc170)