Syncfusion Blazor Chart Export Fails with NullReferenceException

I am experiencing a critical issue with Syncfusion Blazor Chart export when using both RangeColumn and Line series, with the chart width set to 100% and data provided dynamically from the parent component.


Problem Details:

- When the chart width is set to 100% and I click "Export Chart as PNG", the export runs for about 30 seconds and then crashes with the following error:

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=Syncfusion.Blazor
  StackTrace:
   at Syncfusion.Blazor.Charts.SvgPrintExport.TriggerOnExportCompleted(SfChart chart, SfAccumulationChart accChart, String base64String, Boolean isBase64)
   at Syncfusion.Blazor.Charts.SfChart.<ExportAsync>d__836.MoveNext()
   at ...Test.ExportChart() in Test.razor:line 92


- If I set the chart width to a fixed value like `645px`, the export works.

- If I remove the Line series, the export works.

- However, my requirements are:

  - The chart must have both RangeColumn and Line series.

  - The chart must be 100% width (responsive).

  - The data must be provided from the parent (dynamic, not hardcoded in the chart).

- There is no useful error message from Syncfusion, making this extremely difficult to debug. I have spent almost 2 days isolating this issue and creating a minimal repro.

- And the strangest thing is that it works on Syncfusion Online Blazor Playground. 

- My Syncfusion version is "Syncfusion.Blazor" Version="30.1.37" and my Visual Studio is Visual Studio Professional 2022 17.14.4


Steps to Reproduce:

1. Copy the 2 components in the minimal repro to a new project in Visual Studio

2. Run the project

3. Click "Export Chart as PNG"

4. Observe the long delay and then the NullReferenceException

   In the Syncfusion Blazor Playground though, it works. 😕


Minimal Repro:

https://blazorplayground.syncfusion.com/VDryZbrBjEEvlHPj


Request:

- The inconsistent nature of this control has caused many headaches and has been a huge blocking issue for my project and has already caused significant delays. 

- Please investigate and resolve this export issue as soon as possible.


Thank you for your urgent attention to this matter.


4 Replies 1 reply marked as answer

AK Ashish Khanal August 22, 2025 03:22 AM UTC

Repro code (for future reference):


// __Index.razor
<h3>Parent: Fetches Data, Passes to Child</h3>

<style>
    .my-page-stack {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }

    .my-page-stack {
        display: flex;
        flex-direction: column;
        gap: 16px;
        padding-bottom: 16px;
    }
</style>

<div class="my-page-stack">
    @if (loading)
    {
        <p>Loading data...</p>
    }
    else
    {
        <Test Forecasts="@forecasts" AsOfDate="@asOfDate" OnExported="OnExported" @ref="testRef" />
        <button class="e-btn" @onclick="ExportChart" disabled="@exporting">Export Chart as PNG</button>
    }
</div>

@if (!string.IsNullOrEmpty(exportedImage))
{
    <h4>Exported PNG Output (from parent):</h4>
    <div style="border:1px solid #ccc; margin-top:8px; padding:8px;">
        <img src="@exportedImage" style="width:100%;" />
    </div>
}

@if (!string.IsNullOrEmpty(errorMessage))
{
    <div style="color:red; margin-top:10px;">@errorMessage</div>
}

@code {
    private bool loading = true;
    private bool exporting = false;
    private List<List<MyDto>> forecasts = new();
    private DateTime asOfDate = DateTime.Today;
    private Test? testRef;
    private string? exportedImage;
    private string? errorMessage;

    protected override async Task OnInitializedAsync()
    {
        loading = true;
        // Fetch real data from production service later
        forecasts = await GetFakeDataAsync();
        loading = false;
    }

    private async Task ExportChart()
    {
        exporting = true;
        errorMessage = null;
        if (testRef is not null)
        {
            try
            {
                await testRef.ExportChart();
            }
            catch (Exception ex)
            {
                errorMessage = ex.ToString();
            }
        }
        exporting = false;
    }

    private void OnExported(string? base64)
    {
        exportedImage = !string.IsNullOrEmpty(base64) ? $"data:image/png;base64,{base64}" : null;
    }

    private async Task<List<List<MyDto>>> GetFakeDataAsync()
    {
        await Task.Delay(50);
        return new List<List<MyDto>>
        {
            // Prime Model (will be filtered out)
            new List<MyDto>
            {
                new MyDto { DATE = DateTime.Today, MODEL = "Prime Model", PM_VALUE = 15000 },
                new MyDto { DATE = DateTime.Today.AddDays(1), MODEL = "Prime Model", PM_VALUE = 15500 },
                new MyDto { DATE = DateTime.Today.AddDays(2), MODEL = "Prime Model", PM_VALUE = 16000 },
                new MyDto { DATE = DateTime.Today.AddDays(3), MODEL = "Prime Model", PM_VALUE = 16500 },
                new MyDto { DATE = DateTime.Today.AddDays(4), MODEL = "Prime Model", PM_VALUE = 17000 },
                new MyDto { DATE = DateTime.Today.AddDays(5), MODEL = "Prime Model", PM_VALUE = 17500 },
                new MyDto { DATE = DateTime.Today.AddDays(6), MODEL = "Prime Model", PM_VALUE = 14150 }
            },
            // Model 1
            new List<MyDto>
            {
                new MyDto { DATE = DateTime.Today, MODEL = "Model 1", PM_VALUE = 16100 },
                new MyDto { DATE = DateTime.Today.AddDays(1), MODEL = "Model 1", PM_VALUE = 16600 },
                new MyDto { DATE = DateTime.Today.AddDays(2), MODEL = "Model 1", PM_VALUE = 16500 },
                new MyDto { DATE = DateTime.Today.AddDays(3), MODEL = "Model 1", PM_VALUE = 16600 },
                new MyDto { DATE = DateTime.Today.AddDays(4), MODEL = "Model 1", PM_VALUE = 17100 },
                new MyDto { DATE = DateTime.Today.AddDays(5), MODEL = "Model 1", PM_VALUE = 17600 },
                new MyDto { DATE = DateTime.Today.AddDays(6), MODEL = "Model 1", PM_VALUE = 14100 }
            },
            // Model 2
            new List<MyDto>
            {
                new MyDto { DATE = DateTime.Today, MODEL = "Model 2", PM_VALUE = 14000 },
                new MyDto { DATE = DateTime.Today.AddDays(1), MODEL = "Model 2", PM_VALUE = 14400 },
                new MyDto { DATE = DateTime.Today.AddDays(2), MODEL = "Model 2", PM_VALUE = 14900 },
                new MyDto { DATE = DateTime.Today.AddDays(3), MODEL = "Model 2", PM_VALUE = 14400 },
                new MyDto { DATE = DateTime.Today.AddDays(4), MODEL = "Model 2", PM_VALUE = 15900 },
                new MyDto { DATE = DateTime.Today.AddDays(5), MODEL = "Model 2", PM_VALUE = 14400 },
                new MyDto { DATE = DateTime.Today.AddDays(6), MODEL = "Model 2", PM_VALUE = 12900 }
            }
        };
    }

    public class MyDto
    {
        public DateTime DATE { get; set; }
        public string MODEL { get; set; } = "";
        public double? AM_VALUE { get; set; }
        public double? PM_VALUE { get; set; }
    }
}

=================================================================
=================================================================
=================================================================


// Test.razor
@using Microsoft.AspNetCore.Components
@using static Playground.User.__Index

<h3>Child: Receives Data, Transforms, Handles Export</h3>

<style>
    .my-range-chart * {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
</style>

<div class="my-range-chart">
    <Syncfusion.Blazor.Charts.SfChart @ref="chartRef" Title="Range + Line Chart Export Bug" Width="100%">
        <Syncfusion.Blazor.Charts.ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Category" />
        <Syncfusion.Blazor.Charts.ChartPrimaryYAxis Title="Value" Interval="@_mWInterval" Minimum="@AxisMinimum" />
        <Syncfusion.Blazor.Charts.ChartSeriesCollection>
            <Syncfusion.Blazor.Charts.ChartSeries DataSource="@RangeData"
                                                  XName="Category"
                                                  High="High"
                                                  Low="Low"
                                                  Name="Range"
                                                  Type="Syncfusion.Blazor.Charts.ChartSeriesType.RangeColumn"
                                                  Fill="#2196F3"
                                                  Width="2">
                <Syncfusion.Blazor.Charts.ChartMarker Visible="true" Height="5" Width="5">
                    <Syncfusion.Blazor.Charts.ChartDataLabel Visible="true" Position="Syncfusion.Blazor.Charts.LabelPosition.Outer">
                        <Syncfusion.Blazor.Charts.ChartDataLabelFont Size="13px" FontWeight="Bold" Color="Black"></Syncfusion.Blazor.Charts.ChartDataLabelFont>
                    </Syncfusion.Blazor.Charts.ChartDataLabel>
                </Syncfusion.Blazor.Charts.ChartMarker>
            </Syncfusion.Blazor.Charts.ChartSeries>
            <Syncfusion.Blazor.Charts.ChartSeries DataSource="@LineData"
                                                  XName="Category"
                                                  YName="Value"
                                                  Name="Line"
                                                  Type="Syncfusion.Blazor.Charts.ChartSeriesType.Line"
                                                  Fill="#FF9800"
                                                  Width="2">
                <Syncfusion.Blazor.Charts.ChartMarker Visible="true" Height="5" Width="5">
                    <Syncfusion.Blazor.Charts.ChartDataLabel Visible="true" Position="Syncfusion.Blazor.Charts.LabelPosition.Auto">
                        <Syncfusion.Blazor.Charts.ChartDataLabelFont Size="13px" FontWeight="Bold" Color="White"></Syncfusion.Blazor.Charts.ChartDataLabelFont>
                    </Syncfusion.Blazor.Charts.ChartDataLabel>
                </Syncfusion.Blazor.Charts.ChartMarker>
            </Syncfusion.Blazor.Charts.ChartSeries>
        </Syncfusion.Blazor.Charts.ChartSeriesCollection>
        <Syncfusion.Blazor.Charts.ChartLegendSettings Visible="true" EnableHighlight="true" ShapeWidth="9" ShapeHeight="9" Padding="15" />
        <Syncfusion.Blazor.Charts.ChartEvents OnExportComplete="OnExportComplete" />
    </Syncfusion.Blazor.Charts.SfChart>
</div>

@if (!string.IsNullOrEmpty(ErrorMessage))
{
    <div style="color:red; margin-top:10px;">@ErrorMessage</div>
}

@code {

    private Syncfusion.Blazor.Charts.SfChart? chartRef;
    private string? ErrorMessage;

    [Parameter] public List<List<MyDto>> Forecasts { get; set; } = new();
    [Parameter] public DateTime AsOfDate { get; set; }
    [Parameter] public EventCallback<string?> OnExported { get; set; }

    private List<RangeChartPointTest> RangeData = new();
    private List<PrimeModelPointTest> LineData = new();

    private double _mWInterval = 2000;

    private double AxisMinimum => RangeData.Any()
        ? Math.Ceiling((RangeData.Min(r => r.Low) - _mWInterval) / 1000) * 1000
        : 8000;

    protected override void OnParametersSet()
    {
        RangeData = ToRangeChartPoints(AsOfDate, Forecasts);
        LineData = ToPrimeModelPoints(AsOfDate, Forecasts, RangeData.Select(r => r.Category).ToList());
    }

    public async Task ExportChart()
    {
        ErrorMessage = null;
        try
        {
            if (chartRef is not null)
            {
                await chartRef.ExportAsync(Syncfusion.Blazor.Charts.ExportType.PNG, "ChartExport", null, false, true);
            }
        }
        catch (Exception ex)
        {
            ErrorMessage = ex.ToString();
        }
        StateHasChanged();
    }

    private async void OnExportComplete(Syncfusion.Blazor.Charts.ExportEventArgs args)
    {
        try
        {
            if (!string.IsNullOrEmpty(args.Base64))
            {
                await OnExported.InvokeAsync(args.Base64);
            }
            else
            {
                ErrorMessage = "Export failed: No image data returned.";
            }
        }
        catch (Exception ex)
        {
            ErrorMessage = ex.ToString();
        }
        StateHasChanged();
    }

    public static List<RangeChartPointTest> ToRangeChartPoints(DateTime date, List<List<MyDto>> groupedModels)
    {
        var points = new List<RangeChartPointTest>();

        // Only use normal models (exclude "Prime Model")
        var normalGroups = groupedModels.Where(g => !g.All(m => m.MODEL.Trim().ToUpper().StartsWith("PRIME")));

        if (!normalGroups.Any()) return points;
        string[] periods = { "AM", "PM" };

        for (int i = 0; i < 7; i++)
        {
            var day = date.AddDays(i).Date;

            foreach (var period in periods)
            {
                var values = normalGroups
                    .Select(vg => vg.FirstOrDefault(dto => dto.DATE.Date == day))
                    .Select(dto => period == "AM" ? dto?.AM_VALUE : dto?.PM_VALUE)
                    .Where(val => val.HasValue)
                    .Select(val => val.Value)
                    .ToList();

                if (values.Count >= 2)
                {
                    points.Add(new RangeChartPointTest
                    {
                        Category = $"{day:ddd, MM/dd/yyyy} {period}",
                        High = Math.Round(values.Max()),
                        Low = Math.Round(values.Min())
                    });
                }
            }
        }

        return points;
    }

    public static List<PrimeModelPointTest> ToPrimeModelPoints(DateTime date, List<List<MyDto>> groupedModels, List<string> rangeCategories)
    {
        // Use the "Prime Model" as the reference line (or change as needed)
        var primeGroup = groupedModels.FirstOrDefault(g => g.All(m => m.MODEL.Trim().ToUpper() == "PRIME MODEL"));
        if (primeGroup is null) return new();

        var dtoByDate = primeGroup.ToDictionary(d => d.DATE.Date);

        var points = new List<PrimeModelPointTest>();
        string[] periods = { "AM", "PM" };

        for (int i = 0; i < 7; i++)
        {
            var day = date.AddDays(i).Date;
            if (!dtoByDate.TryGetValue(day, out var dto)) continue;

            foreach (var period in periods)
            {
                var category = $"{day:ddd, MM/dd/yyyy} {period}";
                if (!rangeCategories.Contains(category)) continue;

                double? value = period == "AM" ? dto.AM_VALUE : dto.PM_VALUE;
                if (value.HasValue)
                {
                    points.Add(new PrimeModelPointTest
                    {
                        Category = category,
                        Value = Math.Round(value.Value)
                    });
                }
            }
        }

        return points;
    }

    public class RangeChartPointTest
    {
        public string Category { get; set; } = default!;
        public double High { get; set; }
        public double Low { get; set; }
    }

    public class PrimeModelPointTest
    {
        public string Category { get; set; } = default!;
        public double Value { get; set; }
    }
}




DG Durga Gopalakrishnan Syncfusion Team August 22, 2025 10:40 AM UTC

Hi Ashish,


Thank you for reaching out.


We have checked the reported problem with your shared sample. We recommend increasing the MaximumReceiveMessageSize in the Program.cs file to address the connection loss issue when exporting the chart. This will overcome the reported exception. Please check with the below code snippet and sample.


Program.cs

builder.Services.AddSignalR(e =>

{

    e.MaximumReceiveMessageSize = 108544;

});


Sample : https://www.syncfusion.com/downloads/support/directtrac/general/ze/ChartExp.zip


Kindly revert us if you have any concerns.


Regards,

Durga Gopalakrishnan.


Marked as answer

AK Ashish Khanal August 22, 2025 09:23 PM UTC

Hi Durga,

Thank you. That worked!

Would have been great if the error was more helpful; it just threw null reference exception without any meaningful details.

I request Syncfusion to improve the error message, if not document it somewhere on the docs.

Thank you!



DG Durga Gopalakrishnan Syncfusion Team August 26, 2025 02:16 PM UTC

Ashish,


Most welcome. We will include details about increasing the MaximumReceiveMessageSize when exporting charts in our upcoming Knowledge Base article. Once the article is published, we will notify you.


We appreciate your patience and understanding in the meantime.


Please feel free to reach out if you have any further questions or concerns.


Loader.
Up arrow icon