microsoft/aspire · error · InvalidOperationException
No log entry found in OTLP data.
Error message
No log entry found in OTLP data.
What it means
GetStructuredLogJson serializes the first log record from OTLP resource-logs data into a JSON string (for AI/dashboard consumption). It throws InvalidOperationException when the OTLP payload contains no log records at all, i.e. GetLogRecordsFromOtlpData returns an empty sequence, so FirstOrDefault has nothing to return.
Solutions
- Check that resourceLogs is non-null and contains at least one log record before calling GetStructuredLogJson
- Inspect GetLogRecordsFromOtlpData output to confirm the OTLP payload actually decoded records (scopeLogs, logRecords arrays present)
- Guard the call site: only invoke when a prior query returned a non-empty record count
- If an empty result is legitimate for your flow, handle the empty case yourself instead of forcing the throw
Example fix
// before
var json = SharedAIHelpers.GetStructuredLogJson(resourceLogs, getResourceName);
// after
var hasRecords = SharedAIHelpers.GetLogRecordsFromOtlpData(resourceLogs).Any();
var json = hasRecords
? SharedAIHelpers.GetStructuredLogJson(resourceLogs, getResourceName)
: null; // handle empty OTLP data explicitly Defensive patterns
Strategy: validation
Validate before calling
var records = SharedAIHelpers.GetLogRecordsFromOtlpData(resourceLogs); if (!records.Any()) return null; // skip serialization for empty OTLP data
Try / catch
try { return SharedAIHelpers.GetStructuredLogJson(resourceLogs, getResourceName); }
catch (InvalidOperationException) { return null; /* empty OTLP payload */ } Prevention
- Check record count before invoking AI helpers
- Log the raw OTLP payload size when it decodes to zero records
- Filter queries upstream so empty batches skip serialization
When it happens
Trigger: Calling GetStructuredLogJson with an empty or null resourceLogs list, resource logs that contain no scope logs/records, or OTLP JSON that fails to map into any OtlpLogRecord.
Common situations: Passing an empty batch of logs fetched from the OTLP endpoint to an AI assistant prompt; a resource emitted resourceLogs wrapper entries with no actual records; upstream filters removed all records before the call.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- No trace found in OTLP data.
- Cancellation token must be cancellable in order to prevent…
- Circular loop detected for span
- Dimension limit of reached.
- Duplicate span id ' ' detected.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/eb88a4418207d7a0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Shared/ConsoleLogs/SharedAIHelpers.cs:93
var logsData = jsonArray.ToJsonString(s_jsonSerializerOptions);
return (logsData, limitMessage);
}
/// <summary>
/// Converts OTLP resource logs to a single structured log JSON for AI processing.
/// </summary>
/// <param name="resourceLogs">The OTLP resource logs containing log records.</param>
/// <param name="getResourceName">Optional function to resolve resource names.</param>
/// <param name="dashboardBaseUrl">Optional dashboard URL.</param>
/// <returns>The JSON string for the first log entry.</returns>
public static string GetStructuredLogJson(
IList<OtlpResourceLogsJson>? resourceLogs,
Func<IOtlpResource, string> getResourceName,
string? dashboardBaseUrl = null)
{
var logRecords = GetLogRecordsFromOtlpData(resourceLogs);
var logEntry = logRecords.FirstOrDefault() ?? throw new InvalidOperationException("No log entry found in OTLP data.");
var promptContext = new PromptContext();
var dto = GetLogEntryDto(logEntry, promptContext, getResourceName, dashboardBaseUrl);
return dto.ToJsonString(s_jsonSerializerOptions);
}
/// <summary>
/// Converts OTLP resource spans to traces JSON for AI processing.
/// </summary>
/// <param name="resourceSpans">The OTLP resource spans containing trace data.</param>
/// <param name="getResourceName">Optional function to resolve resource names.</param>
/// <param name="dashboardBaseUrl">Optional dashboard URL.</param>
/// <returns>A tuple containing the JSON string and a limit message.</returns>
public static (string json, string limitMessage) GetTracesJson(
IList<OtlpResourceSpansJson>? resourceSpans,
Func<IOtlpResource, string> getResourceName,
string? dashboardBaseUrl = null)
{View on GitHub (pinned to 25830f84bd)