GrapesJS/grapesjs · error
Cannot remove immutable record
Error message
Cannot remove immutable record
What it means
DataSource.removeRecord refuses to delete records marked immutable (`record.mutable === false`) unless the caller explicitly passes `dangerously` in options. This guards records that bound components depend on from being removed unintentionally.
Source
Thrown at packages/core/src/data_sources/model/DataSource.ts:293
em.trigger(em.DataSources.events.providerLoadError, { dataSource, error });
}
};
await fetchProvider();
}
/**
* Removes a record from the data source by its ID.
*
* @param {string | number} id - The ID of the record to remove.
* @param {RemoveOptions} [opts] - Options to apply when removing the record.
* @returns {DataRecord<DRProps> | undefined} The removed data record, or `undefined` if no record is found with the given ID.
* @name removeRecord
*/
removeRecord(id: string | number, opts?: RemoveOptions) {
const record = this.getRecord(id);
if (record?.mutable === false && !opts?.dangerously) {
throw new Error('Cannot remove immutable record');
}
return this.records.remove(id, opts);
}
/**
* Replaces the existing records in the data source with a new set of records.
*
* @param {Array<DRProps>} records - An array of data record properties to set.
* @returns {Array<DataRecord>} An array of the added data records.
* @name setRecords
*/
setRecords(records: DRProps[]) {
this.records.reset([], { silent: true });
records.forEach((record) => {
this.records.add(record);
});View on GitHub (pinned to 2bdeda85b8)
Solutions
- Call `dataSource.removeRecord(id, { dangerously: true })` if the removal is intentional.
- Make the record/schema mutable if records are meant to be managed freely.
- Replace the whole record set with `setRecords` excluding the removed record instead of removing it.
Example fix
// before
dataSource.removeRecord(recordId); // throws for immutable record
// after
dataSource.removeRecord(recordId, { dangerously: true }); Defensive patterns
Strategy: validation
Validate before calling
const record = dataSource.getRecord(id);
if (record && record.mutable === false) {
dataSource.removeRecord(id, { dangerously: true }); // or abort with a UI confirm
} else {
dataSource.removeRecord(id);
} Type guard
function isMutable(r) {
return !!r && r.mutable !== false;
} Try / catch
try {
dataSource.removeRecord(id);
} catch (err) {
if (err.message === 'Cannot remove immutable record') {
const ok = confirm('This record is immutable. Remove anyway?');
if (ok) dataSource.removeRecord(id, { dangerously: true });
} else throw err;
} Prevention
- Inspect record.mutable before delete operations
- Gate destructive UI actions behind explicit user confirmation when records are immutable
- Prefer setRecords with a filtered list over per-record removal for immutable datasets
When it happens
Trigger: Calling `dataSource.removeRecord(id)` on a record with `mutable: false` without `{ dangerously: true }`.
Common situations: Deleting a row fetched from an API whose schema/records are immutable; cleaning up records loaded via a provider; user-driven delete UIs wired to data source records.
Related errors
- Cannot modify immutable record
- Target option is required
- await response.text()
- 'container' is required
- Parser code "${parserCode}" not found
AI-assisted analysis of GrapesJS/grapesjs@2bdeda85b8 (2026-08-30).
Data as JSON: /api/errors/07680790960dff2b.
Report an issue: GitHub.