chenhg5/cc-connect · error
project %q not found
Error message
project %q not found
What it means
executeJob looks up the engine registered for job.Project in the scheduler's engines map. If no engine is registered under that project name, the job cannot run; MarkFired records "project <name> not found" and the job is aborted. This happens when the project referenced by the timer no longer exists or was renamed.
Source
Thrown at core/timer.go:405
ts.executeJob(jobID)
})
ts.timers[jobID] = t
ts.mu.Unlock()
}
func (ts *TimerScheduler) executeJob(jobID string) {
job := ts.store.Get(jobID)
if job == nil || job.Fired {
return
}
ts.mu.RLock()
engine, ok := ts.engines[job.Project]
ts.mu.RUnlock()
if !ok {
slog.Error("timer: project not found", "job", jobID, "project", job.Project)
ts.store.MarkFired(jobID, fmt.Errorf("project %q not found", job.Project))
return
}
slog.Info("timer: executing job", "id", jobID, "project", job.Project, "prompt", truncateStr(job.Prompt, 60))
done := make(chan error, 1)
go func() {
done <- engine.ExecuteTimerJob(job)
}()
var err error
timeout := job.ExecutionTimeout()
if timeout > 0 {
select {
case err = <-done:
case <-time.After(timeout):
err = fmt.Errorf("job timed out after %v", timeout)
}View on GitHub (pinned to 4000b2338a)
Solutions
- Update the job's Project to the current project name and re-register it via AddJob.
- Ensure engines are registered (RegisterEngine/AddEngine) before the scheduler starts or the job's fire time.
- Delete the stale timer from the persisted store if the project is gone intentionally.
- Verify the exact project slug in config.toml matches the one used when creating the timer (case-sensitive).
Example fix
// before
job := &core.TimerJob{Project: "old-name", SessionKey: k, ScheduledAt: when, Prompt: p}
sched.AddJob(job) // engine registered as "new-name"
// after
job := &core.TimerJob{Project: "new-name", SessionKey: k, ScheduledAt: when, Prompt: p}
sched.AddJob(job) Defensive patterns
Strategy: validation
Validate before calling
// ensure the engine is registered before scheduling
if _, ok := sched.EngineFor(projectName); !ok { return fmt.Errorf("project %q has no engine", projectName) }
sched.AddJob(job) Prevention
- Register engines for all configured projects before starting the scheduler
- When renaming/deleting a project, migrate or delete its persisted timers in the same change
- Validate timer project names against config at startup and log/repair mismatches
When it happens
Trigger: AddJob/RegisterEngine ordering issues (job fires before its project engine registered); a config.toml rename of a project while persisted timer jobs still reference the old name; a typo in the job's Project field.
Common situations: Deleting or renaming a project in config without cleaning its timers; restoring an old timer store JSON after a config overhaul; multi-project setups where the timer was created under a different project slug.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- session_key is required
- scheduled_at is required
- either prompt or exec is required
- missed by %v (stale)
- job timed out after %v
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/82f89208b8547f3e.
Report an issue: GitHub.