[SalesForce] Scheduled job hanging in the apex jobs queue

This is one of the strangest things I've seen in SF. There is a mysterious queued scheduled job that can be viewed in apex jobs, but there is no corresponding scheduled job in the scheduled jobs queue, so I am unable to delete it. Furthermore, I am unable to update the schedulable class (which I need to do urgently), because there is a pending job for it. I have tried using system.abortJob to delete the AsyncApexJob, but I get the error that only the parent CronTrigger can be deleted. Okay … so I think maybe there is a CronTrigger that isn't rendering in the scheduled jobs view, so I run anonymous code to query and abort the job – but there is nothing to be found by query. I have no idea how I can fix this. Could this be a bug?

Best Answer

It turns out there was some sort of Salesforce bug. I was able to repeat the issue at will.

Here's the situatuon: I was scheduling a job from a scheduled job. However, because sometimes I have seen scheduled jobs get significantly delayed in their execution, even to the point where it doesn't execute until it's fire time is in the past (which throws "System.AsyncException: Based on configured schedule, the given trigger will never fire."), I used a try catch block, with first system.schedule inside the try braces.

It turns out, when there is in fact such an AsyncException that gets caught, the apex job somehow is scheduled in spite of the caught exception. The obvious problem is however that it's scheduled for a past time that will never be reached. As a result, it hangs indefinitely in the apex jobs queue, but for some reason does not have a corresponding scheduled job to delete, and of course the scheduled class is locked from updating until this is resolved. Feels like a bug to me.

I was able to resolve it by simply copying and deleting the schedulable class, which in turn deleted all corresponding apex jobs (including those which had completed, aborted, etc.). I was then able to easily re-create the class by pasting back in the code.

Instead of using a try catch block, I am now using if statements to compare the scheduled run time with datetime.now(), and if the run time is in the past, I increment it by minutes at a time in a while loop until it becomes later than now. Then the job gets scheduled with the incremented run time.