pardeike/Harmony · error · ArgumentException

VariableState: variable of type

Error message

VariableState: variable of type {type} not found

What it means

VariableState tracks local variables injected during transpiler/emitter workflows, keyed by InjectionType. This indexer getter throws ArgumentException when no LocalBuilder was previously registered under the requested type key.

Solutions

  1. Store the variable first (state[type] = localBuilder) before reading it
  2. Use TryGetValue-style logic via the underlying dictionary or check injected state before indexing
  3. Log/dump the currently registered InjectionType keys to spot the key mismatch

Example fix

// before
var method = state[InjectionType.CurrentMethod];
// after
var local = state.TryGet(InjectionType.CurrentMethod, out var l) ? l : throw new InvalidOperationException("Run InjectVariable first");
Defensive patterns

Strategy: validation

Validate before calling

if (!state.InjectedTypes.Contains(type)) throw new InvalidOperationException($"{type} not injected yet");
var local = state[type];

Try / catch

try { local = state[type]; } catch (ArgumentException) { local = il.DeclareLocal(expectedType); state[type] = local; }

Prevention

When it happens

Trigger: Querying state[SomeInjectionType] (e.g. state[InjectionType.CurrentMethod] or similar) in an emitter/transpiler helper before anything has stored a LocalBuilder for that InjectionType key.

Common situations: A transpiler registered extra variables under one injection type but reads them under another; two transpilers assume each other populated the state; refactor renamed an InjectionType so the store call no longer matches the lookup.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at Harmony/Internal/VariableState.cs:24

{
	internal class VariableState
	{
		readonly Dictionary<InjectionType, LocalBuilder> injected = [];
		readonly Dictionary<string, LocalBuilder> other = [];

		public void Add(InjectionType type, LocalBuilder local) => injected[type] = local;
		public void Add(string name, LocalBuilder local) => other[name] = local;

		public bool TryGetValue(InjectionType type, out LocalBuilder local) => injected.TryGetValue(type, out local);
		public bool TryGetValue(string name, out LocalBuilder local) => other.TryGetValue(name, out local);

		public LocalBuilder this[InjectionType type]
		{
			get
			{
				if (injected.TryGetValue(type, out var local))
					return local;
				throw new ArgumentException($"VariableState: variable of type {type} not found");
			}
			set => injected[type] = value;
		}

		public LocalBuilder this[string name]
		{
			get
			{
				if (other.TryGetValue(name, out var local))
					return local;
				throw new ArgumentException($"VariableState: variable named '{name}' not found");
			}
			set => other[name] = value;
		}
	}
}

View on GitHub (pinned to e7872dc170)