microsoft/aspire · error
Instrument limit of reached. Instrument ' ' will not be…
Error message
Instrument limit of {TelemetryRepositoryLimits.MaxInstrumentCount} reached. Instrument '{metric.Name}' will not be added. What it means
The Dashboard repository caps the number of distinct metric instruments stored per resource at TelemetryRepositoryLimits.MaxInstrumentCount. Before inserting a new instrument row, GetOrAddCachedInstrument counts existing instruments for the resource and throws when the cap is already reached, preventing unbounded cardinality from a faulty emitter.
Solutions
- Fix the emitting app to stop creating instruments with unbounded/dynamic names (create instruments once at startup, not per request).
- Increase TelemetryRepositoryLimits.MaxInstrumentCount if the app legitimately needs more instruments per resource.
- Restart or clear dashboard telemetry storage to reset the count after fixing the emitter.
- Use the dashboard UI (Limits) to view configured limits and confirm the cap that was hit.
Example fix
// before: instrument per request
var counter = meter.CreateCounter<long>($"requests.{orderId}");
// after: fixed instrument, order id as a tag/attribute
var counter = meter.CreateCounter<long>("app.requests");
counter.Add(1, new KeyValuePair<string, object?>("order.id", orderId)); Defensive patterns
Strategy: validation
Validate before calling
if (instrumentNameIsDynamic) // names derived from request data
{
throw new InvalidOperationException("Instrument names must be static; use attributes for variability.");
} Try / catch
try
{
await repository.AddMetricsAsync(...);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Instrument limit"))
{
logger.LogWarning(ex, "Instrument cardinality limit hit; fix emitting app.");
} Prevention
- Create instruments once at startup with static names.
- Never embed ids/timestamps in instrument names; use attributes instead.
- Monitor distinct instrument names per service in dev before production.
When it happens
Trigger: AddMetricToDatabase -> GetOrAddCachedInstrument runs for a resource that already has MaxInstrumentCount instruments in telemetry_metric_instruments, and the incoming metric.Name is not yet among the cached instruments.
Common situations: A service emitting metrics with high-cardinality names (e.g. names embedding ids or timestamps); a long-running dashboard that accumulated instruments from many deployments of the same resource; a runaway loop generating new instrument names.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Dimension limit of reached.
- Histogram data point bucket count length changed.
- Histogram data point has bucket counts without any explicit…
- Histogram data point sum must be finite.
- Instrument name is required.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/114753b74d3e7212.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Dashboard/Otlp/Storage/SqliteTelemetryRepository.Caching.cs:293
{
if (resourceScope.Instruments.TryGetValue(metric.Name, out var instrument))
{
return instrument;
}
EnsureCachedInstrumentsLoaded(connection, transaction, resource, resourceScope);
if (resourceScope.Instruments.TryGetValue(metric.Name, out instrument))
{
return instrument;
}
var instrumentCount = resource.InstrumentCount ??= connection.QuerySingle<int>(
"SELECT COUNT(*) FROM telemetry_metric_instruments WHERE resource_id = @ResourceId;",
new { resource.ResourceId },
transaction);
if (instrumentCount >= TelemetryRepositoryLimits.MaxInstrumentCount)
{
throw new InvalidOperationException($"Instrument limit of {TelemetryRepositoryLimits.MaxInstrumentCount} reached. Instrument '{metric.Name}' will not be added.");
}
var instrumentId = connection.QuerySingle<long>("""
INSERT INTO telemetry_metric_instruments (
resource_id, resource_view_id, scope_id, instrument_name, description, unit, instrument_type,
aggregation_temporality, is_monotonic)
VALUES (
@ResourceId, @ResourceViewId, @ScopeId, @InstrumentName, @Description, @Unit, @InstrumentType,
@AggregationTemporality, @IsMonotonic)
RETURNING instrument_id;
""", new
{
resource.ResourceId,
resourceView.ResourceViewId,
ScopeId = resourceScope.Scope.ScopeId,
InstrumentName = metric.Name,
metric.Description,
metric.Unit,View on GitHub (pinned to 25830f84bd)