[SalesForce] SOQL query to load Task returns nothing, but I see task in UI

I am trying to load all tasks of a contact via SOQL query:

SELECT Id, Subject FROM Task WHERE WhoId = 'contactId'

This query returns only partial list of Tasks. I.e. in UI I see tasks directly attached to this Contact which are not being returned as part of the result for this query.

I googled a bit and found out that I might need to query an ActivityHistory sobject and yes querying it returns me "missing" tasks as well:

SELECT (SELECT Id, Subject FROM ActivityHistories) FROM Contact WHERE Id ='contactId'

So, my question is that an expected behavior? I.e. there is no way to load all the Tasks using 1 query and I have to load both Tasks and AcitivityHistories?

Also, interestingly, I couldn't reproduce this situation in a developer account: I've registered a Task with subject 'other' that took place in the past and in UI it is displayed in Activity History section, but I receive it is a part of normal Task loading query. So, i am not really sure why the Task in originally described situation is not returned with simple Task query (i.e. only in ActivityHistories query)

Best Answer

Salesforce archives older activities. From the docs:

How can I view activities that are more than a year old?
Salesforce archives older activities according to the conditions below. These activities can be viewed only in the Printable View of the associated record, the Activity History related list of the associated record, export files, or by clicking View All on the Activity History related list. You can search for archived activities using advanced search. Administrators can also delete archived activities using Mass Delete.

  1. Events with a due date greater than 365 days old
  2. Closed tasks with a due date greater than 365 days old
  3. Closed tasks without a due date that were created more than 365 days ago

When these conditions are meet* the Task no longer appears in SOQL queries against the Task sObject. Instead you need to use the ActivityHistory "view" in a relationship query from the parent sObject.

* It appears the archival process isn't immediate. If you set a Tasks Due Date to be more than one year old it will still appear against the Task sObject for a period of time. Most likely Salesforce has a scheduled job to process the archival.


Useful notes from the docs:

  • ActivityHistory a "read-only object contains information about each activity related to an object". "This object helps you replicate the related list functionality of the user interface."
    So ActivityHistory is more like a view that collectively returns both Tasks and Events and archived records.
  • Task "Represents a business activity such as making a phone call or other “to-do” items. In the user interface, task and Event records are collectively referred to as activities."
  • Event "Represents a calendar appointment event. In the user interface, Event and Task records are collectively referred to as activities."

A couple of other thoughts as to why you might see a record in ActivityHistory but not in Task.

  1. The record in question is an Event and not a Task. Check the keyprefix in the Id. If it is 00U then you are dealing with an Event. A Task would be 00T. Or check the IsTask ActivityHistory column.
    As per the discussion, we have confirmed that you are dealing with a task
  2. There might be sharing rules/permission issues hiding the record in question. Does the user running the query have the View All Data permission?
  3. The task might have a due date greater than 365 days old and has been archived by Salesforce. See How can I view activities that are more than a year old?
Related Topic