diff --git a/public/app/features/dashboard/state/DashboardModel.ts b/public/app/features/dashboard/state/DashboardModel.ts index 097ae6453c4..57c2efa86a9 100644 --- a/public/app/features/dashboard/state/DashboardModel.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -525,6 +525,14 @@ export class DashboardModel implements TimeModel { } } + // Also check panels in legacy rows (pre-v16 dashboard format) + // This ensures unique IDs are assigned before the row upgrade migration runs + for (const panel of this.rawPanelIterator()) { + if (panel.id > max) { + max = panel.id; + } + } + return max + 1; } @@ -539,6 +547,26 @@ export class DashboardModel implements TimeModel { } } + /** + * Iterates over panels from the original raw dashboard data, including legacy rows. + * This is needed to find panel IDs before row upgrade migration runs. + */ + private *rawPanelIterator() { + // @ts-expect-error - rows is a legacy property not included in the modern Dashboard schema + const rows = this.originalDashboard?.rows; + + if (Array.isArray(rows)) { + for (const row of rows) { + const rowPanels = row?.panels; + if (Array.isArray(rowPanels)) { + for (const panel of rowPanels) { + yield panel; + } + } + } + } + } + forEachPanel(callback: (panel: PanelModel, index: number) => void) { for (let i = 0; i < this.panels.length; i++) { callback(this.panels[i], i);