The Apex job named "<name>" is already scheduled for execution
You called `System.schedule(name, ...)` with a name that's already in use. The platform refuses duplicate-name schedules. Either abort the existing one first, or pick a unique name (e.g., suffix with timestamp).
Also seen asalready scheduled for execution·Apex job is already scheduled·schedule name conflict
System.schedule(name, cronExp, jobInstance) requires name to be unique among active schedules. Reusing a name fails immediately.
The shape of the bug
System.schedule('Daily_Reconciliation', '0 0 1 * * ?', new ReconJob());
// Some time later, in the same org:
System.schedule('Daily_Reconciliation', '0 0 1 * * ?', new ReconJob());
// ❌ already scheduled
Fix 1: abort the old one before scheduling
List<CronTrigger> existing = [
SELECT Id FROM CronTrigger
WHERE CronJobDetail.Name = 'Daily_Reconciliation'
];
for (CronTrigger ct : existing) {
System.abortJob(ct.Id);
}
System.schedule('Daily_Reconciliation', '0 0 1 * * ?', new ReconJob());
This pattern lets your deploy idempotently re-schedule the job — useful when you want the cron expression to update from one release to the next.
Fix 2: use a uniquely-suffixed name
String name = 'Daily_Reconciliation_' + System.now().getTime();
System.schedule(name, '0 0 1 * * ?', new ReconJob());
This bypasses the conflict but accumulates one new schedule per call. Watch for the scheduled-job-limit cap of 100. Most teams use Fix 1 (abort + re-schedule) for production schedules.
Fix 3: ScheduleBatch with a unique ID
For one-time deferred work, System.scheduleBatch returns a job ID and the name is auto-derived:
Id jobId = System.scheduleBatch(new MyBatch(), 'OneTime_' + UserInfo.getUserId(), 5);
The job runs once, 5 minutes from now. No persistent schedule to manage.
Diagnose: list all current schedules
SELECT Id, CronJobDetail.Name, NextFireTime, State, OwnerId
FROM CronTrigger
WHERE CronJobDetail.JobType = '7' -- Scheduled Apex
ORDER BY CronJobDetail.Name
Run this in the Developer Console's Query Editor. Each row is one scheduled job. Look for duplicates or stale entries.
A common deploy-time issue
CI pipelines that include System.schedule calls in post-deploy hooks fail on the second run because the schedule from the first run is still active. Always pair the schedule with an upfront abort.
A clean post-deploy script pattern:
// In a deploy script or post-deploy class:
String JOB_NAME = 'Nightly_Reconciliation';
List<CronTrigger> existing = [SELECT Id FROM CronTrigger WHERE CronJobDetail.Name = :JOB_NAME];
for (CronTrigger ct : existing) System.abortJob(ct.Id);
System.schedule(JOB_NAME, '0 0 2 * * ?', new ReconJob());
Idempotent. Re-run safe. Always.
