Article Salesforce Integration Not Updating Opportunity Status

Yeah this one tripped me up too when I first looked at it. If you're seeing work orders complete in FieldPulse but the linked Salesforce Opportunity just sits there at "Prospecting" or whatever your default is, you're probably hitting a edge case around custom picklist values.

What's happening

The Salesforce integration maps FieldPulse work order status → Opportunity StageName. When we query your Salesforce org to build that mapping, we paginate through the PicklistValues metadata. Problem is: if you've got a custom field with more than 100 picklist options (yeah, I've seen it — one org had 247 stages for some reason), we only get the first page. So if your actual live Opportunity Stage values fall outside that first 100, the sync silently fails to find a match and... doesn't update anything. No error, no warning, just a no-op.

Solid reproduction

// This'll show you if you're affected
GET /services/data/v58.0/sobjects/Opportunity/describe
// Look for StageName.picklistValues — count 'em

If that array's truncated at 100 and your target stage is #103, boom, that's your bug.

Current status

Fix targeted for 3.3 — we're moving to the newer /tooling/sobjects/FieldDefinition endpoint which handles large picklists properly. ETA late March.

Workaround for now

Two options, neither great:

  1. Trim your picklists. If you've got 200+ stages, some of those are probably dead anyway. Archive the unused ones and bring yourself under 100. I know, I know — "go clean up your Salesforce" is never the answer people want.
  2. Manual webhook bridge. Fire a webhook on work_order.status_changed, hit your own middleware, and call Salesforce's REST API directly with the right StageName. More work, but it sidesteps our metadata query entirely. There's a thread on webhook troubleshooting here if you go this route.

Related: if you're also seeing Zapier triggers missing custom fields, it's the same underlying pagination issue across our Salesforce metadata fetching. Fixing one fixes both.

Will update this thread when the 3.3 beta drops. If you're on the beta program and want to test the fix early, hit me up.

  • From a governance perspective, it is worth noting that picklists exceeding 100 values often indicate architectural debt in Salesforce configuration. While the technical fix is appreciated, organizations experiencing this issue should audit whether their Opportunity stages align with documented sales processes.

    It is also worth noting that the silent failure mode — HTTP 200 with no field updates — violates principle of fail-closed design for financial system integrations. I would recommend escalation to security review for post-incident analysis once resolved.

  • Nice — yeah that's basically what we're implementing on our side, though we're switching to Tooling API to avoid the describe call overhead entirely. The FieldDefinition endpoint gives you the full picklist in one shot regardless of size.

    Heads up though: if you're using a session-scoped metadata API call, watch out for INVALID_SESSION_ID on long-running syncs. We've seen that bite people when the mapping runs against 10k+ records.

  • Quick patch on your end if you need something before March:

    // Middleware to handle the pagination
    const getAllPicklistValues = async (conn, sobject, field) => {
      let values = [];
      let url = `/sobjects/${sobject}/describe`;
      
      do {
        const res = await conn.request(url);
        const fieldMeta = res.fields.find(f => f.name === field);
        values.push(...fieldMeta.picklistValues);
        url = fieldMeta.nextPageUrl; // or parse from response
      } while (url);
      
      return values;
    };

    Then map explicitly before your update call. Not pretty but it unblocks you.

  • I can reproduce this consistently in our sandbox. Salesforce API returns exactly 100 picklist values with nextPageUrl populated, which the integration does not follow. I have confirmed that:

    • FieldPulse v3.2.0 build 2847
    • Salesforce API v58.0
    • Custom Opportunity Stage field with 156 values
    • Target stage "Closed Won - Referral" is item #127 in the full list

    Sync log shows HTTP 200 with empty updatedFields array. No error surfaced to UI.