6

The raw debug log starts with a header line like the following:

37.0 APEX_CODE,FINEST;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,INFO;WORKFLOW,INFO

From the Debug Log - Inspecting the Debug Log Sections docs (my emphasis):

The header contains the following information.

  • The version of the API used during the transaction.
  • The log category and level used to generate the log.

For an inbound API call the version used is clearly defined in the URL.

What determines the API version if the request started in the standard Salesforce UI, such as a standard page layout?

This question was derived from the same question on twitter by Johan Yu.
In that thread it was reported that two orgs both on Summer '16 were giving different API versions in the header based on the associated trigger API version. With the order of trigger execution being arbitrary when there are multiple triggers for the same event, can the API version for the log then be equally variable?

  • 3
    The Summer '16 release has totally flubbed the debugging functionality. – Adrian Larson Jun 20 '16 at 21:20
  • 1
    Flubbed is the polite word for it. – Caspar Harmer Jun 20 '16 at 21:25
  • Expected behavior should be that it uses the API Version specified on the Visualforce Page methinks. Odds that behavior conforms to expectation... – Adrian Larson Jun 20 '16 at 21:33
  • 1
    @AdrianLarson From twitter Johan Yu was indicating that it was a standard page layout. No Visualforce involved. I'd assumed that it would take the latest API version in that case. But it didn't appear to be functioning like that. – Daniel Ballinger Jun 20 '16 at 21:36
  • How else do you initiate an Apex request from the standard Page Layout? Just on an ordinary save? – Adrian Larson Jun 20 '16 at 21:37
2

As far as I can tell, the system uses two simple rules: the first compiled unit's version, or the API request version if no compiled code is involved.

The first rule can cause problems when a lower-versioned class or trigger runs first. As I've said before, you should make a conscious effort to set all of your classes to the same version. The first encountered version determines the behavior for the transaction.

If no compiled units are in play, then the API request version is used. This applies to all API calls where no code is involved, or where no compiled code is involved (e.g. executeAnonymous that does not invoke any compiled code), or when using the UI (in which case, it is the latest version).

When multiple triggers on the same object are involved, one will be selected to go first, and consequently determine the API version of the entire transaction. In that case, the version will be unpredictable if the triggers are on different API versions. This doesn't apply when those triggers are invoked from a Visualforce page or Apex class (e.g. via @RemoteAction).

I'm not going to test every conceivable combination, but based on simple experimentation, I'd say at least most of this answer is accurate. For that reason, I strongly recommend that you keep all of your code at the same API version to avoid surprises. This includes unit tests, because the unit tests will determine the API version for the called classes.


Edit: I just realized that I should mention that the "header" version that's displayed is not necessarily what each Apex Class or trigger will function at. It determines some behaviors, but certainly not all behaviors. This makes things a lot more complex. For example, the exact version of the API you use on a class should determine if JSON.serialize includes null values or not, or if String.split('') will include a blank string at index 0. The first class that performs a query seems to set the API version for all subsequent queries in the transaction. It gets really complicated to try and predict what will work and what will not.

  • That certainly seems to agree with what is being observed. I'd comment that my usage of executeAnonymous has always followed the API version defined the the SOAP URL. – Daniel Ballinger Jun 21 '16 at 0:11
  • The whole multiple triggers with one selected to go first and define the API version could get exciting when managed packages are involved. Then you potentially lose control of the version that gets used. – Daniel Ballinger Jun 21 '16 at 0:13
  • 1
    @DanielBallinger Added some clarification. The system has an entire list of various features that are versioned, such as JSON null values, String.split behavior, and queries/describes. For example, the Known Issue I linked to in this answer demonstrates that executeAnonymous can fail depending on the order of queries; clearly the database engine maintains its own version separate from the request API version. As far as I know, there's no definitive list of what honors the request API and what honors the class/trigger's API. – sfdcfox Jun 21 '16 at 0:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.