{"record":{"id":"b6c814f35a0fd7d2","repo":"microsoft/aspire","slug":"resource-limit-of-otlpcontext-options-maxresourcecount","errorCode":null,"errorMessage":"Resource limit of {_otlpContext.Options.MaxResourceCount} reached. Resource '{resourceKey}' will not be added.","messagePattern":"Resource limit of (.+?) reached\\. Resource '(.+?)' will not be added\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Aspire.Dashboard/Otlp/Storage/SqliteTelemetryRepository.Caching.cs","lineNumber":82,"sourceCode":"                    \"\"\", new { ResourceName = resourceKey.Name, resourceKey.InstanceId }, transaction);\n                if (record is not null)\n                {\n                    cachedResource = GetOrAddCachedResource(record);\n                    if (cachedResource.Resource.UninstrumentedPeer && !uninstrumentedPeer)\n                    {\n                        connection.Execute(\n                            \"UPDATE telemetry_resources SET uninstrumented_peer = 0 WHERE resource_id = @ResourceId;\",\n                            new { cachedResource.ResourceId },\n                            transaction);\n                    }\n                    cachedResource.Resource.SetUninstrumentedPeer(uninstrumentedPeer);\n                }\n                else\n                {\n                    var resourceCount = connection.QuerySingle<int>(\"SELECT COUNT(*) FROM telemetry_resources;\", transaction: transaction);\n                    if (resourceCount >= _otlpContext.Options.MaxResourceCount)\n                    {\n                        throw new InvalidOperationException($\"Resource limit of {_otlpContext.Options.MaxResourceCount} reached. Resource '{resourceKey}' will not be added.\");\n                    }\n\n                    var resourceId = connection.QuerySingle<long>(\"\"\"\n                        INSERT INTO telemetry_resources (resource_name, instance_id)\n                        VALUES (@ResourceName, @InstanceId)\n                        RETURNING resource_id;\n                        \"\"\", new { ResourceName = resourceKey.Name, resourceKey.InstanceId }, transaction);\n                    cachedResource = CreateCachedResource(resourceId, resourceKey, uninstrumentedPeer);\n                }\n            }\n\n            GetOrAddCachedResourceView(connection, transaction, cachedResource, []);\n            return cachedResource;\n        }\n    }\n\n    private CachedResourceView GetOrAddCachedResourceView(\n        SqliteConnection connection,","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Dashboard/Otlp/Storage/SqliteTelemetryRepository.Caching.cs#L64-L100","documentation":"The SQLite-backed telemetry repository caps the number of distinct telemetry resources it persists via _otlpContext.Options.MaxResourceCount. GetOrAddCachedResource throws this InvalidOperationException when inserting a new resource would exceed that limit; the resource (and its telemetry) is not added. The limit protects Dashboard memory/storage from hosts generating unbounded numbers of unique resources.","triggerScenarios":"GetOrAddCachedResource throws when SELECT COUNT(*) FROM telemetry_resources equals or exceeds MaxResourceCount and a resource key not yet in the cache is added from AddLogsToDatabaseAsync, AddMetricsToDatabaseAsync, or AddTracesToDatabaseAsync. Triggered on OTLP ingestion when telemetry arrives identifying more unique resources than the configured maximum.","commonSituations":"Applications emitting resource attributes with per-instance/per-deploy unique values so every restart looks like a new resource; very large service fleets pointed at one Dashboard instance; one-off ephemeral jobs each creating a distinct resource; deployment with a lowered MaxResourceCount option.","solutions":["Raise the MaxResourceCount option in the Dashboard/OTLP context configuration if the workload legitimately needs more resources.","Stabilize resource attributes (service.name, instance ids) so processes are not counted as new resources on every restart.","Filter or reduce the number of distinct services/instances exporting to this Dashboard (e.g. via collector filtering)."],"exampleFix":"// before: default or lowered limit\noptions.MaxResourceCount = 500;\n// after: accommodate the fleet size\noptions.MaxResourceCount = 5000;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    await repository.AddTracesToDatabaseAsync(batch);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Resource limit of\"))\n{\n    logger.LogWarning(ex, \"Resource limit reached; resource '{Key}' dropped.\", resourceKey);\n}","preventionTips":["Size MaxResourceCount to the expected number of distinct services/instances.","Keep resource attributes stable across restarts so instances are not counted repeatedly.","Monitor resource growth and filter ephemeral jobs away from the Dashboard."],"tags":["opentelemetry","limits","resource","sqlite","dashboard"],"backgroundTag":"resource-limit-exceeded","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}