Skip to main content

Deploying a Master-Detail ↔ Lookup Conversion (and Why Validate Fails)

Short answer: converting a relationship field between Master-Detail and Lookup is a supported Metadata API change — a real deployment works in both directions. What Salesforce blocks is validating it. A test-only (checkOnly / "Validate") deploy that includes the conversion fails with:

Test only deployment cannot update a field from a Master-Detail to Lookup Test only deployment cannot update a field from a Lookup to MasterDetail

Salesforce rejects it in test-only mode to avoid data loss or corruption. The fix is to run a real deployment instead — the deploy itself performs the validation. (To validate ahead of production, do a full deploy to a spare sandbox.)

Why Validate is blocked but a real deploy works​

Changing the relationship type rewrites how child records relate to their parent, and on a large object that touches data. Salesforce won't do that work in a test-only run — a Validate is supposed to be side-effect-free, and this change can't be. So the platform blocks the conversion during checkOnly and only performs it during a real deployment, where it can apply the change and its data consequences together. This is a platform policy on test-only deploys, not a bug in your package or your deployment tool — it applies to change sets, the CLI, and any tool with a Validate button.

The data preconditions each direction needs​

A real deploy still fails if the data isn't ready. These are Salesforce platform rules (Considerations for Converting a Custom Field's Type):

  • Master-Detail → Lookup — no roll-up summary fields may exist on the parent object. Once a roll-up summary references the relationship, the conversion is blocked until you delete it.
  • Lookup → Master-Detail — every child record must already have a parent. Any record with a blank lookup blocks the conversion. It also can't be done if the child object's org-wide default is Controlled by Parent.
  • Permanent deletion caveat — in a Lookup → Master-Detail deploy, detail records must reference a master or be soft-deleted, and a successful deployment permanently deletes any detail records sitting in the Recycle Bin. This is the "data loss" the Validate block exists to prevent.

The side effects worth knowing​

The conversion silently changes sharing, and can break reporting:

  • Master-Detail → Lookup flips the object's org-wide default to Public Read/Write.
  • Lookup → Master-Detail flips it to Controlled by Parent.
  • Reports built on the old relationship type can become unusable — Salesforce recommends re-testing custom reports after converting.

How mtdt.io warns you before you waste a Validate run​

Because mtdt.io has a first-class Validate button, it catches this before you hit it. When your deployment includes a field whose relationship type differs between source and target, the pre-deployment checks flag it:

mtdt.io's pre-deployment check warning that a Master-Detail ↔ Lookup change can't be validated, naming the field and its direction

  • In Validate mode, mtdt.io shows a Master-Detail ↔ Lookup change can't be validated warning naming the field and direction, so you switch to a real deploy instead of burning a Validate run on a change Salesforce will reject.
  • In Deploy mode, it shows a softer note reminding you of the data preconditions (roll-up summaries, blank lookups, the OWD flip).
  • If the conversion slips through to a run anyway, the deploy result decodes the terse Test only deployment cannot update a field… failure into a plain-English explanation and the next step.

To be clear about the limits: mtdt.io steers you off the one path Salesforce forbids and explains the failure — it doesn't make the conversion validate (nothing can), and it doesn't check your record data for orphan children or roll-up summaries. Those remain your call before a real deploy.

FAQ​

Can you deploy a Master-Detail to Lookup change in Salesforce? Yes — in a real deployment. Both Master-Detail → Lookup and Lookup → Master-Detail deploy through the Metadata API, as long as the data preconditions are met. It's not a manual-only change. What you can't do is validate it.

Why does "Test only deployment cannot update a field from a Master-Detail to Lookup" appear? Because you're running a Validate (test-only / checkOnly) deployment. Salesforce blocks a Master-Detail ↔ Lookup conversion in test-only mode to avoid data loss, and fails the whole package. Run a real deployment instead — it performs the validation itself.

How do I validate the change before production then? Do a full (real) deployment to a separate test sandbox. A real deploy includes validation as part of the process, so a spare sandbox gives you the pre-flight check that Validate can't.

What has to be true for the conversion to succeed? For Master-Detail → Lookup, delete any roll-up summary fields on the parent first. For Lookup → Master-Detail, every child record must already reference a parent (no blank lookups), and detail records in the Recycle Bin are permanently deleted by the deploy.

Will converting the relationship change my sharing settings? Yes. Master-Detail → Lookup sets the object's org-wide default to Public Read/Write; Lookup → Master-Detail sets it to Controlled by Parent. Re-test custom reports afterward, since reports on the old relationship type can break.