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

  1. Fix the emitting app to stop creating instruments with unbounded/dynamic names (create instruments once at startup, not per request).
  2. Increase TelemetryRepositoryLimits.MaxInstrumentCount if the app legitimately needs more instruments per resource.
  3. Restart or clear dashboard telemetry storage to reset the count after fixing the emitter.
  4. 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

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


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)