pardeike/Harmony · error · Exception

Wrong Emit argument type

Error message

Wrong Emit argument type {operand.GetType()} in {codeInstruction}

What it means

For InlineSig (calli) instructions Harmony requires the operand to implement ICallSiteGenerator. If the operand is non-null but of another type (e.g. a SignatureHelper from a different emitter abstraction or a random object), EmitCodes throws this instead of silently emitting broken IL.

Solutions

  1. Ensure the calli operand is created via the same IL generator's SignatureHelper/ICallSiteGenerator mechanism.
  2. Rebuild the signature for the calli site instead of copying the operand from a read body.
  3. Check that all Harmony patching assemblies reference the same Harmony version.

Example fix

// before
instr.operand = someMethodInfo; // wrong type for calli

// after
instr.operand = il.CreateSignature(...); // proper ICallSiteGenerator signature
Defensive patterns

Strategy: type-guard

Validate before calling

foreach (var ci in transpiledInstructions)
    if (ci.opcode.OperandType == OperandType.InlineSig && ci.operand is not null && ci.operand is not ICallSiteGenerator)
        throw new InvalidOperationException($"Bad calli operand type {ci.operand.GetType()}");

Type guard

static bool IsCallSiteOperand(object operand) => operand is ICallSiteGenerator;

Try / catch

try { harmony.Patch(original, transpiler: t); }
catch (Exception ex) when (ex.Message.Contains("Wrong Emit argument type"))
{ Logger.Error($"Bad calli operand: {ex.Message}"); }

Prevention

When it happens

Trigger: A transpiler assigns a wrong-typed operand to a calli instruction — for example a SignatureHelper created for a different IL generator, a byte array, or a MethodInfo — and the wrapper is emitted.

Common situations: Reusing transpiler code across IL emitter versions, copying calli operands from a MethodInfo body reader into CodeInstruction without converting, or mixing Harmony versions where the signature type differs.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of pardeike/Harmony@e7872dc170 (2026-09-15). Data as JSON: /api/errors/e5eb24461f4622e1. Report an issue: GitHub.

Appendix: source

Thrown at Harmony/Internal/MethodCreatorTools.cs:636

				// start all exception blocks
				codeInstruction.blocks.Do(block => emitter.MarkBlockBefore(block, out var _));

				var code = codeInstruction.opcode;
				var operand = codeInstruction.operand;

				switch (code.OperandType)
				{
					case OperandType.InlineNone:
						if (codeInstruction.IsAnnotation() == null)
							emitter.Emit(code);
						break;

					case OperandType.InlineSig:
						if (operand is null)
							throw new Exception($"Wrong null argument: {codeInstruction}");
						if ((operand is ICallSiteGenerator) is false)
							throw new Exception($"Wrong Emit argument type {operand.GetType()} in {codeInstruction}");
						emitter.Emit(code, (ICallSiteGenerator)operand);
						break;

					default:
						if (operand is null)
							throw new Exception($"Wrong null argument: {codeInstruction}");
						emitter.DynEmit(code, operand);
						break;
				}

				codeInstruction.blocks.Do(block => emitter.MarkBlockAfter(block));
			});
		}

		static List<CodeInstruction> InitializeOutParameter(int argIndex, Type type)
		{
			var codes = new List<CodeInstruction>();
			if (type.IsByRef)

View on GitHub (pinned to e7872dc170)