The Deploy Succeeded but the Field Doesn't Exist: Salesforce's Invisible-Field Trap
Fields deployed via the Metadata API ship with no field-level security for anyone — not even admins. Why your new field is invisible, and the permission-set fix.
Here’s a sequence that will make you doubt your own tooling. You deploy a new custom field to a Salesforce org — the deployment reports Succeeded, the field shows up in Object Manager, everything looks normal. Then you query it and get “No such column on entity Contact.” A report builder search can’t find it. Even logged in as a full System Administrator, the field behaves like it was never created.
You didn’t break anything. You’ve hit one of the platform’s least-advertised rules: fields created through the Metadata API ship with no field-level security for anyone. Not your integration user, not your staff profiles, not System Administrator. The field exists at the schema level and is invisible to every human until something explicitly grants access.
Why clicking never taught you this
Create a field through the Setup wizard and the last screen asks which profiles can see it — with admins pre-checked. The wizard quietly does the field-level security (FLS) step for you, so most admins have never seen a field exist without it.
Deployments — change sets, the CLI, CI/CD pipelines, a consultant pushing from a sandbox — skip that wizard. The field arrives, the FLS step doesn’t, and the deploy still reports success because, technically, everything you asked for was done.
The part that makes it genuinely confusing
Apex code runs in system mode for field access — it ignores FLS entirely. So if the new field is written by code (a form handler, an integration, a trigger), the code keeps working perfectly while every human query insists the field doesn’t exist. Data flows in; nobody can see it. I’ve watched a public intake form happily save to fields that no user in the org — including me, the admin who deployed them — could query. The combination reads like a haunted org until you know the rule. (A form wired to a field that was never created produces the same empty columns from the other direction — the silent data drop.)
The fix: ship a permission set with the fields
The durable pattern is to treat FLS as part of the deployment itself: a small permission set that grants read/edit on the new fields, deployed alongside them and assigned to the people who need it.
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
<label>My Feature Fields</label>
<fieldPermissions>
<field>Contact.My_New_Field__c</field>
<readable>true</readable>
<editable>true</editable>
</fieldPermissions>
</PermissionSet>
This beats editing profiles directly — it’s explicit, versionable, easy to assign to exactly the right people, and it documents why the access exists. (It’s also the general direction Salesforce has been pushing for years: permission sets over profile sprawl.)
The five-minute diagnosis
Next time a “successfully deployed” field acts missing:
- Object Manager → the object → Fields & Relationships. Field listed? It deployed fine.
- Click the field → Set Field-Level Security. If every profile shows unchecked, you’ve found it.
- Grant access — permission set preferred, the FLS button works in a pinch — and the field instantly “exists” everywhere it was missing.
If you take one habit from this: when reviewing any deployment that adds fields, ask “where’s the permission set?” If the answer is a blank look, the org is about to gain some very well-hidden data.