{"record":{"id":"72b1023d175a4653","repo":"GrapesJS/grapesjs","slug":"cannot-modify-immutable-record","errorCode":null,"errorMessage":"Cannot modify immutable record","messagePattern":"Cannot modify immutable record","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/data_sources/model/DataRecord.ts","lineNumber":153,"sourceCode":"   *\n   * @param {String|Object} attributeName - The name of the attribute to set, or an object of key-value pairs.\n   * @param {any} [value] - The value to set for the attribute.\n   * @param {Object} [options] - Options to apply when setting the attribute.\n   * @param {Boolean} [options.avoidTransformers] - If true, transformers will not be applied.\n   * @returns {DataRecord} - The instance of the DataRecord.\n   * @name set\n   * @example\n   * record.set('name', 'newValue');\n   * // Sets 'name' property to 'newValue'\n   */\n  set<A extends _StringKey<T>>(\n    attributeName: DeepPartialDot<T> | A,\n    value?: SetOptions | T[A] | undefined,\n    options?: SetOptions | undefined,\n  ): this;\n  set(attributeName: unknown, value?: unknown, options?: SetOptions): DataRecord {\n    if (!this.isNew() && this.attributes.mutable === false) {\n      throw new Error('Cannot modify immutable record');\n    }\n\n    const onRecordSetValue = this.dataSource?.transformers?.onRecordSetValue;\n\n    const applySet = (key: string, val: unknown, opts: SetOptions = {}) => {\n      const newValue =\n        opts?.avoidTransformers || !onRecordSetValue\n          ? val\n          : onRecordSetValue({\n              id: this.id,\n              key,\n              value: val,\n            });\n      super.set(key, newValue, opts);\n      // This ensures to trigger the change event with partial updates\n      super.set({ __p: opts.partial ? true : undefined } as any, opts);\n    };\n","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/GrapesJS/grapesjs/blob/2bdeda85b82b8b9ceae42fd6558cbbcae5ec2d21/packages/core/src/data_sources/model/DataRecord.ts#L135-L171","documentation":"DataRecord instances in the GrapesJS Data Sources layer can be marked immutable (`attributes.mutable === false`). Once a record is persisted/created (isNew() false) and immutable, `set()` refuses all mutations to protect records that other parts (components bound via data sources) depend on.","triggerScenarios":"Calling `record.set(key, value)` (directly or via `dataResolver`/path updates like `resetDataSourcePath`/`setDataResolver`/`upSchema`) on an existing record whose `mutable` flag is false.","commonSituations":"Fetching records from a provider with schema defined as non-mutable, then trying to update a record value; mutating records loaded by `dataSource.load()`; API changes where records default to immutable after creation.","solutions":["Create a new record instead of mutating, or remove and re-add the record with new values.","Set `mutable: true` in the record/schema definition when creating the data source if mutations are intended.","Use `opts` on the collection/schema level that allows mutation, or reset the whole data source via `setRecords`/`setDataResolver` rather than setting individual fields."],"exampleFix":"// before\nrecord.set('title', 'new value'); // throws on immutable record\n// after\ndatasource.removeRecord(record.id);\ndatasource.addRecord({ id: record.id, title: 'new value' });","handlingStrategy":"try-catch","validationCode":"if (record && record.isNew && !record.isNew() && record.get('mutable') === false) {\n  // treat as read-only: skip set or recreate the record\n}","typeGuard":"function isMutableRecord(r) {\n  return !r || r.isNew() || r.attributes?.mutable !== false;\n}","tryCatchPattern":"try {\n  record.set('title', value);\n} catch (err) {\n  if (err.message === 'Cannot modify immutable record') {\n    datasource.removeRecord(record.id, { dangerously: true });\n    datasource.addRecord({ ...record.attributes, title: value });\n  } else throw err;\n}","preventionTips":["Check the `mutable` flag (or schema definition) before mutating records","Design schemas with mutable:true if records need in-place updates","Treat fetched records as immutable snapshots and write new records for changes"],"tags":["grapesjs","data-sources","immutability","state"],"backgroundTag":"immutable-record-modification","analyzedSha":"2bdeda85b82b8b9ceae42fd6558cbbcae5ec2d21","analyzedAt":"2026-08-30T11:47:52.267Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}