AG Grid can validate your configuration during development and report problems that are otherwise easy to miss in the console. Enable these diagnostics in development builds only — they are not part of the AllCommunityModule / AllEnterpriseModule bundles, so production stays small.
Enabling Validation Copy Link
Call enableDevValidations once, before any grid is created:
import { enableDevValidations } from 'ag-grid-community';
if (process.env.NODE_ENV !== 'production') {
enableDevValidations();
}This is equivalent to registering the module directly with ModuleRegistry.registerModules([ValidationModule]).
Without the module, console messages are reduced to an error code and a documentation link rather than the full text.
Options Copy Link
Pass options to enableDevValidations to configure:
import { enableDevValidations } from 'ag-grid-community';
enableDevValidations({
showOverlayOn: ['deprecation', 'warning', 'error'],
throwOn: ['warning', 'error'],
suppress: [],
});If you register the module explicitly (instead of using enableDevValidations), then pass the same options via ValidationModule.with({ showOverlayOn: ['deprecation', 'warning', 'error'], throwOn: ['warning', 'error'], suppress: [] })
Configuration is global and applies to every grid on the page, with the options from the last call being used.
Overlay Copy Link
The overlay lists the diagnostics captured for a grid on top of that grid, with controls to copy them or dismiss the overlay. It is shown by default.
Diagnostics have one of three severities:
'deprecation'— use of a deprecated option or feature'warning'— a likely misconfiguration the grid can recover from'error'— an invalid configuration
Set showOverlayOn to an array of the severities to show. For example, to show warnings and errors but not deprecations:
enableDevValidations({ showOverlayOn: ['warning', 'error'] });Defaults to ['deprecation', 'warning', 'error'] (every severity). Pass [] to hide the overlay.
In the example below, a column definition includes a property the grid does not recognise, so the resulting warnings surface in the overlay:
import {
createApp,
defineComponent,
onBeforeMount,
ref,
shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
AllCommunityModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
GridReadyEvent,
ModuleRegistry,
enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
ModuleRegistry.registerModules([AllCommunityModule]);
let api: GridApi;
const VueExample = defineComponent({
template: `
<div style="height: 100%">
<ag-grid-vue
style="width: 100%; height: 100%;"
@grid-ready="onGridReady"
:columnDefs="columnDefs"
:rowData="rowData"></ag-grid-vue>
</div>
`,
components: {
"ag-grid-vue": AgGridVue,
},
setup(props) {
const gridApi = shallowRef<GridApi | null>(null);
const columnDefs = ref<ColDef[]>([
// A stray property the grid does not recognise (as a prop-spreading wrapper might add),
// surfacing warnings #307 (per property) and #310 (summary) in the overlay.
{ field: "make", notAColumnProperty: true } as ColDef,
{ field: "model" },
{ field: "price" },
]);
const rowData = ref<any[] | null>([
{ make: "Tesla", model: "Model Y", price: 64950 },
{ make: "Ford", model: "F-Series", price: 33850 },
{ make: "Toyota", model: "Corolla", price: 29600 },
]);
const onGridReady = (params: GridReadyEvent) => {
gridApi.value = params.api;
};
return {
gridApi,
columnDefs,
rowData,
onGridReady,
};
},
});
const app = createApp(VueExample);
app.mount("#app");
Each grid shows only its own diagnostics. A nested grid (such as a detail grid in a Master / Detail grid) surfaces its diagnostics on its own overlay, not the parent's. When grid creation fails before the grid exists (for example, a row model with no row-model module registered) there is no grid to overlay. A standalone panel is shown in its place.
Throwing on Problems Copy Link
throwOn turns matching diagnostics into thrown errors instead of console messages, so problems fail fast rather than scrolling past unnoticed. This suits automated workflows (for example, end-to-end test runs or AI-assisted development) where a hard failure is surfaced to be acted on immediately.
Set throwOn to an array of the severities to throw on. For example, to throw on errors only:
enableDevValidations({ throwOn: ['error'] });Defaults to [] (never throws).
throwOn throws synchronously wherever a matching diagnostic is raised. That is not only at start-up, it also happens during API calls, data updates, and rendering. A throw can interrupt an operation part-way and leave the grid in an inconsistent state. Use throwOn with harnesses that recreate the grid on failure rather than carrying on with the same instance, and never in production.
Reacting to Diagnostics in Code Copy Link
The issueRaised event fires for every captured diagnostic, so tooling can react to problems programmatically instead of watching the console. This suits CI gates, test harnesses and AI-assisted development loops that need to collect diagnostics and act on them.
const gridOptions = {
onIssueRaised: (event) => {
// { id: 307, severity: 'warning', message: '...', attributedToThisGrid: true }
collectForReport(event);
},
};As with any grid event, you can also subscribe with the API:
api.addEventListener('issueRaised', (event) => collectForReport(event));The event provides:
id— the diagnostic's number, as shown in the console message and the overlay, for example307severity— one of the severities abovemessage— the diagnostic text, as written to the console at that severityattributedToThisGrid— whether this grid raised the diagnostic (see below)
Like the rest of development validation, the event needs the ValidationModule registered. Without it no diagnostics are captured, so the callback is inert rather than an error — a callback left in a production build costs nothing but never fires.
The event is not filtered by showOverlayOn or throwOn: it fires for every diagnostic regardless of which are shown in the overlay, and it fires before a matching throwOn throws. Diagnostics you have suppressed do not fire the event, as suppressing an id opts out of it entirely.
In the example below, a column definition includes a property the grid does not recognise, and the resulting diagnostics are listed under the grid:
import {
createApp,
defineComponent,
onBeforeMount,
ref,
shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
AllCommunityModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
GridReadyEvent,
IssueRaisedEvent,
ModuleRegistry,
enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
enableDevValidations({ showOverlayOn: [] });
}
ModuleRegistry.registerModules([AllCommunityModule]);
let api: GridApi;
const VueExample = defineComponent({
template: `
<div style="height: 100%">
<div style="display: flex; flex-direction: column; height: 100%">
<ag-grid-vue
style="width: 100%; height: 100%;"
@grid-ready="onGridReady"
:columnDefs="columnDefs"
:rowData="rowData"
@issue-raised="onIssueRaised"></ag-grid-vue>
<div style="flex: none; padding: 8px 0">
<div>Diagnostics reported to <code>onIssueRaised</code>:</div>
<ul id="issueList"></ul>
</div>
</div>
</div>
`,
components: {
"ag-grid-vue": AgGridVue,
},
setup(props) {
const gridApi = shallowRef<GridApi | null>(null);
const columnDefs = ref<ColDef[]>([
// A stray property the grid does not recognise (as a prop-spreading wrapper might add),
// surfacing warnings #307 (per property) and #310 (summary).
{ field: "make", notAColumnProperty: true } as ColDef,
{ field: "model" },
{ field: "price" },
]);
const rowData = ref<any[] | null>([
{ make: "Tesla", model: "Model Y", price: 64950 },
{ make: "Ford", model: "F-Series", price: 33850 },
{ make: "Toyota", model: "Corolla", price: 29600 },
]);
function onIssueRaised(event: IssueRaisedEvent) {
const item = document.createElement("li");
item.textContent = `#${event.id} (${event.severity}): ${event.message}`;
document.querySelector("#issueList")!.appendChild(item);
}
const onGridReady = (params: GridReadyEvent) => {
gridApi.value = params.api;
};
return {
gridApi,
columnDefs,
rowData,
onGridReady,
onIssueRaised,
};
},
});
const app = createApp(VueExample);
app.mount("#app");
The same diagnostic can be raised more than once. The event fires each time, so deduplicate in your handler if you only want each distinct problem once:
const seen = new Set();
const gridOptions = {
onIssueRaised: (event) => {
const key = `${event.severity}#${event.id}:${event.message}`;
if (!seen.has(key)) {
seen.add(key);
collectForReport(event);
}
},
};Some diagnostics cannot be attributed to a particular grid — a theme created outside any grid, or an API call on a grid that has already been destroyed. These are delivered to every live grid with attributedToThisGrid: false. Check the flag if you only want this grid's own problems.
Diagnostics raised before the grid exists — such as a row model with no row-model module registered, which stops the grid being created at all — are reported to the console and the standalone panel, but not through this event, as there is no grid to fire it from.
Suppressing Diagnostics Copy Link
Suppressing diagnostics hides real problems and is a last resort. Reach for it only when the cause is outside your control, for example: a third-party wrapper you cannot change
suppress takes the error ids to ignore, for diagnostics you have reviewed and accepted. A suppressed id is kept out of the overlay and is never thrown by throwOn, but is still logged to the console once. Suppression is by id, so it silences every diagnostic with that number — not one specific occurrence.
For example, a third-party wrapper you cannot change spreads unrelated props onto your column definitions, so the grid reports properties it does not recognise — a per-property warning (307) and a summary (310). Suppress both while the source is out of your control:
enableDevValidations({
suppress: [
307, // "did you mean …" raised for each unrecognised property
310, // the "one or more properties are not recognised" summary
],
});The id is the number shown in the console message and the overlay, for example #310.