pardeike/Harmony · error · Exception

cannot set value of method

Error message

cannot set value of method {_method.FullDescription()}

What it means

Traverse.SetValue can only write fields and properties. If the traversal's current member is a method, there is no settable value, so Harmony throws with the method's full description to identify the offending path member.

Solutions

  1. Re-position the traverse on the field/property with .Field()/.Property() before SetValue
  2. Use a separate Traverse instance for method invocation vs value access
  3. Check the target member is not a method: Traverse.Create(t).Field("f").SetValue(x)

Example fix

// before
var tr = Traverse.Create(f).Method("Compute"); tr.Value = 5; // method has no value
// after
Traverse.Create(f).Field("result").SetValue(5);
Defensive patterns

Strategy: validation

Validate before calling

var member = Traverse.Create(obj).Field("result");
if (!member.FieldExists()) throw new InvalidOperationException("target is not a settable field/property");
member.SetValue(5);

Type guard

bool IsSettableMember(this Traverse tr) => tr.FieldExists() || tr.PropertyExists();

Try / catch

try { tr.Value = value; }
catch (Exception ex) when (ex.Message.StartsWith("cannot set value of method")) { /* re-point traverse at a field/property */ }

Prevention

When it happens

Trigger: Calling traverse.SetValue(value) (or the .Value shortcut) on a traverse positioned on a method via .Method(...), instead of on a field or property.

Common situations: Reusing a traverse variable that was last pointed at a method; confusing .GetValue() (method invoke) with .Value (field/property access); property with no setter resolved oddly so only the getter method was found.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at Harmony/Tools/Traverse.cs:170

		public T GetValue<T>(params object[] arguments)
		{
			if (_method is null)
				throw new Exception("cannot get method value without method");
			return (T)_method.Invoke(_root, arguments);
		}

		/// <summary>Sets a value of the current field or property</summary>
		/// <param name="value">The value</param>
		/// <returns>The same traverse instance</returns>
		///
		public Traverse SetValue(object value)
		{
			if (_info is FieldInfo)
				((FieldInfo)_info).SetValue(_root, value, AccessTools.all, null, CultureInfo.CurrentCulture);
			if (_info is PropertyInfo)
				((PropertyInfo)_info).SetValue(_root, value, AccessTools.all, null, _params, CultureInfo.CurrentCulture);
			if (_method is not null)
				throw new Exception($"cannot set value of method {_method.FullDescription()}");
			return this;
		}

		/// <summary>Gets the type of the current field or property</summary>
		/// <returns>The type</returns>
		///
		public Type GetValueType()
		{
			if (_info is FieldInfo)
				return ((FieldInfo)_info).FieldType;
			if (_info is PropertyInfo)
				return ((PropertyInfo)_info).PropertyType;
			return null;
		}

		/// <summary>Checks if the current traverse instance is for a field</summary>
		/// <returns>True if its a field</returns>
		///

View on GitHub (pinned to e7872dc170)