{"record":{"id":"82f89208b8547f3e","repo":"chenhg5/cc-connect","slug":"project-q-not-found-82f892","errorCode":null,"errorMessage":"project %q not found","messagePattern":"project %q not found","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/timer.go","lineNumber":405,"sourceCode":"\t\tts.executeJob(jobID)\n\t})\n\tts.timers[jobID] = t\n\tts.mu.Unlock()\n}\n\nfunc (ts *TimerScheduler) executeJob(jobID string) {\n\tjob := ts.store.Get(jobID)\n\tif job == nil || job.Fired {\n\t\treturn\n\t}\n\n\tts.mu.RLock()\n\tengine, ok := ts.engines[job.Project]\n\tts.mu.RUnlock()\n\n\tif !ok {\n\t\tslog.Error(\"timer: project not found\", \"job\", jobID, \"project\", job.Project)\n\t\tts.store.MarkFired(jobID, fmt.Errorf(\"project %q not found\", job.Project))\n\t\treturn\n\t}\n\n\tslog.Info(\"timer: executing job\", \"id\", jobID, \"project\", job.Project, \"prompt\", truncateStr(job.Prompt, 60))\n\n\tdone := make(chan error, 1)\n\tgo func() {\n\t\tdone <- engine.ExecuteTimerJob(job)\n\t}()\n\n\tvar err error\n\ttimeout := job.ExecutionTimeout()\n\tif timeout > 0 {\n\t\tselect {\n\t\tcase err = <-done:\n\t\tcase <-time.After(timeout):\n\t\t\terr = fmt.Errorf(\"job timed out after %v\", timeout)\n\t\t}","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/timer.go#L387-L423","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\njob := &core.TimerJob{Project: \"old-name\", SessionKey: k, ScheduledAt: when, Prompt: p}\nsched.AddJob(job) // engine registered as \"new-name\"\n// after\njob := &core.TimerJob{Project: \"new-name\", SessionKey: k, ScheduledAt: when, Prompt: p}\nsched.AddJob(job)","handlingStrategy":"validation","validationCode":"// ensure the engine is registered before scheduling\nif _, ok := sched.EngineFor(projectName); !ok { return fmt.Errorf(\"project %q has no engine\", projectName) }\nsched.AddJob(job)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["timer","scheduler","lookup"],"backgroundTag":"entity-not-found","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}