dotnet/BenchmarkDotNet · error · NotSupportedException

Passing ref readonly structs by ref is not supported (cannot

Error message

Passing ref readonly structs by ref is not supported (cannot store {0} as a class field).

What it means

The InProcess emit-based runner stores arguments in class fields, which is impossible for ref readonly structs; passing such parameters by ref is therefore unsupported.

Source

Thrown at src/BenchmarkDotNet/Toolchains/InProcess/Emit/Implementation/Emitters/RunnableEmitter.cs:317

                    else if (parameterType.IsByRefLike() && argValue.Value != null)
                    {
                        argLocalsType = parameterType;

                        // Use conversion on load; store passed value
                        var passedArgType = argValue.Value.GetType();
                        opConversion = GetImplicitConversionOpFromTo(passedArgType, argLocalsType)
                            ?? throw new InvalidOperationException($"Bug: No conversion from {passedArgType} to {argLocalsType}.");
                        argFieldType = passedArgType;
                    }
                    else
                    {
                        // No conversion; load ref to arg field;
                        argLocalsType = parameterType;
                        argFieldType = parameterType;
                    }

                    if (argFieldType.IsByRefLike())
                        throw new NotSupportedException($"Passing ref readonly structs by ref is not supported (cannot store {argFieldType} as a class field).");

                    var argField = fieldsContainerBuilder.DefineField(
                        ArgFieldPrefix + parameter.Position,
                        argFieldType,
                        FieldAttributes.Public);

                    argFields.Add(new(argField, argLocalsType, opConversion));
                }

                EmitExtraFields(fieldsContainerBuilder);

                // private FieldsContainer __fieldsContainer;
                fieldsContainerField = runnableBuilder.DefineField(
                    FieldsContainerName,
                    fieldsContainerBuilder,
                    FieldAttributes.Private);
            }
        }

View on GitHub (pinned to b515068b61)

Solutions

  1. Avoid passing ref readonly structs (e.g. Span<T>, ReadOnlySpan<T>) as ref arguments to the benchmark method.
  2. Pass the ref struct by value, or wrap the state in a reference type / field of the benchmark class instead.
  3. Use the out-of-process (default) toolchain if ref-by-ref struct passing is unavoidable.

When it happens

Trigger: Thrown at src/BenchmarkDotNet/Toolchains/InProcess/Emit/Implementation/Emitters/RunnableEmitter.cs:317 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13). Data as JSON: /api/errors/c7766d7eca41d9c7. Report an issue: GitHub.