dotnet/BenchmarkDotNet · error · InvalidOperationException
There is no default resolver for {characteristic.FullId}
Error message
There is no default resolver for {characteristic.FullId} What it means
CompositeResolver.Resolve(CharacteristicObject, Characteristic) throws when the object does not already hold a value for the requested characteristic AND none of the resolvers in its chain can resolve it. CompositeResolver aggregates several IResolver instances (job/runtime/infrastructure resolvers) and resolves a characteristic by delegating to the first capable resolver; if the list is empty for that characteristic, there is no way to produce a default.
Source
Thrown at src/BenchmarkDotNet/Characteristics/CompositeResolver.cs:24
{
private readonly IResolver[] resolvers;
public CompositeResolver(params IResolver[] resolvers)
{
this.resolvers = resolvers;
}
public bool CanResolve(Characteristic characteristic) => resolvers.Any(r => r.CanResolve(characteristic));
public object? Resolve(CharacteristicObject obj, Characteristic characteristic)
{
if (obj.HasValue(characteristic))
return characteristic[obj];
var resolver = resolvers.FirstOrDefault(r => r.CanResolve(characteristic));
if (resolver != null)
return resolver.Resolve(obj, characteristic);
throw new InvalidOperationException($"There is no default resolver for {characteristic.FullId}");
}
public T? Resolve<[DynamicallyAccessedMembers(CharacteristicObject.CharacteristicMemberTypes)] T>(CharacteristicObject obj, Characteristic<T> characteristic)
{
if (obj.HasValue(characteristic))
return characteristic[obj];
var resolver = resolvers.FirstOrDefault(r => r.CanResolve(characteristic));
if (resolver != null)
return resolver.Resolve(obj, characteristic);
throw new InvalidOperationException($"There is no default resolver for {characteristic.FullId}");
}
public object? Resolve(CharacteristicObject obj, Characteristic characteristic, object defaultValue)
{
if (obj.HasValue(characteristic))
return characteristic[obj];
View on GitHub (pinned to b515068b61)
Solutions
- Ensure the resolver you pass to the CompositeResolver can resolve the characteristic (call CanResolve on it) before relying on Resolve.
- Set an explicit value on the characteristic (e.g. job.WithRuntime(...)) so the HasValue short-circuit applies instead of resolver lookup.
- Add the missing resolver (typically the framework/runtime/infrastructure default resolver) to the composite.
- If you do not need a value, call the Resolve(obj, characteristic, defaultValue) overload that returns a default instead of throwing.
Example fix
// before
var value = composite.Resolve(job, SomeCharacteristic);
// after
if (composite.CanResolve(SomeCharacteristic))
var value = composite.Resolve(job, SomeCharacteristic);
else
job = job.With(SomeCharacteristic, fallbackValue); Defensive patterns
Strategy: validation
Validate before calling
if (!composite.CanResolve(characteristic))
throw new InvalidOperationException($"Caller must set '{characteristic.Id}' before resolve.");
var value = composite.Resolve(obj, characteristic); Type guard
bool CanResolveSafely(CompositeResolver r, Characteristic c) => r.CanResolve(c);
Try / catch
try { return composite.Resolve(obj, characteristic); }
catch (InvalidOperationException ex) when (ex.Message.Contains("no default resolver"))
{
// set a sensible default or rethrow with context about the missing characteristic
} Prevention
- Always include the resolver that owns a characteristic when building a CompositeResolver.
- Set explicit values on characteristics you depend on rather than relying on resolver defaults.
- Prefer the Resolve(obj, characteristic, defaultValue) overload when a fallback is acceptable.
When it happens
Trigger: Calling obj.ResolveValue / Job.ResolveValue for a characteristic that was never set and for which no resolver (e.g. InfrastructureResolver, RuntimeResolver, JobResolver) was registered in the composite. Building a custom CompositeResolver whose resolver list omits the resolver that owns a given characteristic.
Common situations: Creating a hand-rolled resolver chain for tests or a custom hosting scenario, referencing a characteristic that only exists in a newer/older BDN version than the resolvers you wired up, or mutating a Job's resolver set after construction.
Related errors
- The current object {this} is frozen. Create a copy to modify
- The current operation allowed for root nodes only, but the v
- There is no default resolver for {characteristic.FullId}
- The value {value} is not assignable to {characteristic} prop
- The argument must be an array
AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13).
Data as JSON: /api/errors/4f412d3329d47977.
Report an issue: GitHub.