Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

devkon98's avatar

Canvas is already in use. Chart with ID '1' must be destroyed before the canvas can be reused.

Hello i am 2 graphs made in ChartJs and they are dynamic, meaning they get values from API and the values with its tags change. Now i get this error Canvas is already in use. Chart with ID '1' must be destroyed before the canvas can be reused. when i try to change data from calendar. This is my code that destroys the first chart and makes a new one but doesnt work :

async function cashReceivedGraph(label) {

    const ctx = document.getElementById('cashReceivedGraph').getContext('2d');

    let data = 0;
    let configuration = 0;
    let allCurrencyName = [];

    for (i in label) {
        const item = label[i];
        allCurrencyName.push(item.name);
    }

    let allCurrencyDatasets =

        allCurrencyName.map(currency => (
            {
                label: currency,
                borderColor: cashGenerateRandomColor(),
                data: this.getCashDatasetsForOneCurrency(currency)
            }
        ),
    )

    data = {
        labels: cashCreated_date,
        datasets: allCurrencyDatasets
    };

    configuration = {

        type: 'line',

        data,

        option: {
            tooltip: {
                mode: 'index'
            }
        }
    };

    if (chart) {
        chart.destroy();
        chart = new Chart(ctx, configuration);
    } else {
        charts = new Chart(ctx, configuration);
    }
}
0 likes
2 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

The issue is that the chart variable is not defined anywhere in the code. You need to define it outside of the cashReceivedGraph function so that it can be accessed and destroyed later. Here's an updated version of the code:

let chart; // define chart variable outside of function

async function cashReceivedGraph(label) {
  const ctx = document.getElementById('cashReceivedGraph').getContext('2d');

  let data = 0;
  let configuration = 0;
  let allCurrencyName = [];

  for (i in label) {
    const item = label[i];
    allCurrencyName.push(item.name);
  }

  let allCurrencyDatasets = allCurrencyName.map((currency) => ({
    label: currency,
    borderColor: cashGenerateRandomColor(),
    data: this.getCashDatasetsForOneCurrency(currency),
  }));

  data = {
    labels: cashCreated_date,
    datasets: allCurrencyDatasets,
  };

  configuration = {
    type: 'line',
    data,
    option: {
      tooltip: {
        mode: 'index',
      },
    },
  };

  if (chart) {
    chart.destroy();
    chart = new Chart(ctx, configuration);
  } else {
    chart = new Chart(ctx, configuration);
  }
}

Now, the chart variable is defined outside of the function and can be accessed and destroyed as needed.

2 likes
kokoshneta's avatar

While the variable should be set outside the function, the primary issue in your original code is that the if branch will never be executed, and the chart object therefore never destroyed.

You check to see if chart (singular) is set, but you never actually set chart anywhere – in the else branch you set charts (plural), which is then never referred to again. So every time you update, it will attempt to set charts again without destroying anything.

To simplify things, you could just set the chart info outside the if statement:

if (chart) chart.destroy();
chart = new Chart(ctx, configuration);
2 likes

Please or to participate in this conversation.