Not verified hands-on. This article was written from primary documentation rather than reproduced in an org, so it carries no tested-release badge. If you run it and something differs, say so in the comments and it gets tested and corrected.

Short answer: you put a value in a field the platform will not let you write. Formula fields, roll-up summaries, most system audit fields and anything read-only for your profile all behave the same way: the write is rejected and the field is named. In the API you get INVALID_FIELD_FOR_INSERT_UPDATE. In Apex you usually never get that far, because the compiler stops you.

INVALID_FIELD_FOR_INSERT_UPDATE:
Unable to create/update fields: Total_Revenue__c. Please check the
security settings of this field and verify that it is read-only for
your profile or permission set.

The message is misleading on purpose

It blames security settings, and that is only one of the possible causes. The other causes produce the same wording, which sends people to permission sets when the field could never have been written by anybody.

Work through these in order:

  • Is it a formula field? Formulas are computed on read. There is nothing stored to write. No permission makes them writeable.
  • Is it a roll-up summary? Same answer. The value comes from the children.
  • Is it an autonumber? Assigned by the platform on insert.
  • Is it a system field? CreatedDate, CreatedById, LastModifiedDate, LastModifiedById, SystemModstamp, Id on insert.
  • Is it a calculated standard field? Account.IsPersonAccount, Opportunity.HasOpportunityLineItem, Case.IsClosed and their relatives are derived, not stored for you.
  • Only then, check field-level security. If the field is a plain custom field and none of the above applies, the profile or permission set has it as read-only.

In Apex you get a compile error instead

Apex knows at compile time which fields are not writeable, so the failure arrives earlier and reads differently:

Account a = new Account(Name = 'Test');
a.CreatedDate = System.now();
// Field is not writeable: Account.CreatedDate

This is better. A save failure in the IDE beats a runtime failure in a data load. It also means a runtime INVALID_FIELD_FOR_INSERT_UPDATE in Apex nearly always comes from dynamic code, where the field name is a string and the compiler had nothing to check:

SObject rec = Schema.getGlobalDescribe().get(objName).newSObject();
rec.put(fieldName, value);   // fails at runtime if fieldName is a formula

Describe gives you the answer before you try. isCreateable() and isUpdateable() on the field describe cover both the field’s own nature and the running user‘s permissions, which is what you want for generic code:

Schema.DescribeFieldResult d = fieldToken.getDescribe();
if (d.isUpdateable()) { rec.put(d.getName(), value); }

The audit field exception

Created and last modified fields are writeable on insert only, and only when the org and the user are both set up for it. This exists for data migrations, where preserving the original creation date matters.

Two steps, and both are needed:

  1. In Setup, under User Interface, enable the setting for creating records with audit field values. It is off by default.
  2. Grant the “Set Audit Fields upon Record Creation” user permission through a permission set to the migration user.

After that, an insert may set CreatedDate, CreatedById, LastModifiedDate and LastModifiedById. Update is still refused. You get one chance, at insert, and after the record exists those values are fixed. Migration teams that discover this on day three of a cutover rebuild a lot of data.

A sensible precaution is to turn the permission off again once the migration is done. An audit field that can be set is an audit field that can be wrong.

What to do when you need the value somewhere else

If you find yourself wanting to write a formula field, the requirement is usually to store a snapshot: what the value was at a point in time, rather than what it is now. That needs a separate writeable field populated by a flow or a trigger. Trying to make the formula writeable is the wrong shape of solution and there is no way to do it regardless.

For a roll-up summary, the equivalent is a custom number field maintained by code, which is what you already need when the relationship is a lookup rather than master-detail.

Frequently asked

Why does the error name a field I did not touch? Data Loader sends every mapped column, including ones you exported and did not intend to update. Unmap the read-only columns rather than blanking them.

Can a System Administrator write a formula field? No. This is not a permission question. There is no stored value to write.

Does OwnerId belong on this list? Not usually. It is writeable, but it has its own rules: some objects do not allow an owner change in the same DML as other edits, and the failure looks different.

How do I list the writeable fields on an object? Iterate the describe and filter on isUpdateable(). That gives the answer for the running user, which is the only answer that matters at runtime.