chenhg5/cc-connect · error

cron project not found

Error message

cron project not found

What it means

ErrCronProjectNotFound is the sentinel error returned by RunJobNow when a job exists but its referenced project is missing — the job's Project name does not resolve to a configured cron project. It is wrapped with the project name and asserted in cron_test.go. Unlike a missing job, the job id itself was valid.

Source

Thrown at core/cron.go:52

	Mute        bool      `json:"mute,omitempty"`         // suppress ALL messages (start + result); job runs silently
	SessionMode string    `json:"session_mode,omitempty"` // "" or "reuse" = share active session; "new_per_run" = fresh session each run
	Mode        string    `json:"mode,omitempty"`         // permission mode override for this job; "" = use project default
	TimeoutMins *int      `json:"timeout_mins,omitempty"` // nil = default 30m wait; 0 = no limit; >0 = minutes
	CreatedAt   time.Time `json:"created_at"`
	LastRun     time.Time `json:"last_run,omitempty"`
	LastError   string    `json:"last_error,omitempty"`
}

// IsShellJob returns true if the job runs a shell command directly.
func (j *CronJob) IsShellJob() bool {
	return j.Exec != ""
}

const defaultCronJobTimeout = 30 * time.Minute

var (
	ErrCronJobNotFound     = errors.New("cron job not found")
	ErrCronProjectNotFound = errors.New("cron project not found")
)

// ExecutionTimeout returns how long the scheduler waits for the job goroutine to finish.
// nil TimeoutMins uses 30 minutes. *TimeoutMins == 0 means wait without a time limit.
// *TimeoutMins > 0 means that many minutes.
func (j *CronJob) ExecutionTimeout() time.Duration {
	if j.TimeoutMins == nil {
		return defaultCronJobTimeout
	}
	if *j.TimeoutMins <= 0 {
		return 0
	}
	return time.Duration(*j.TimeoutMins) * time.Minute
}

// UsesNewSessionPerRun reports whether each cron run should use a new engine session
// instead of reusing the active session for the session_key.
func (j *CronJob) UsesNewSessionPerRun() bool {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Re-add or fix the project name in config so job.Project resolves
  2. Update or delete the orphaned cron job that references the missing project
  3. Use errors.Is(err, ErrCronProjectNotFound) to surface a 404/config-repair message to API clients
  4. Reload config after editing to ensure jobs and projects are consistent

Example fix

// before
projects:
  - name: "deploy"   # job references "ghost"
// after
projects:
  - name: "deploy"
  - name: "ghost"    # or update the job to reference "deploy"
Defensive patterns

Strategy: try-catch

Validate before calling

job := scheduler.Store().Get(jobID)
if job != nil && scheduler.Project(job.Project) == nil {
    return fmt.Errorf("job %q references missing project %q", jobID, job.Project)
}

Type guard

func isCronProjectNotFound(err error) bool { return errors.Is(err, ErrCronProjectNotFound) }

Try / catch

if err := scheduler.RunJobNow(jobID); err != nil {
    if errors.Is(err, ErrCronProjectNotFound) {
        log.Warn("cron job references missing project; fix config", "err", err)
        return
    }
    return err
}

Prevention

When it happens

Trigger: Calling scheduler.RunJobNow for a job whose job.Project names a project that is absent from the scheduler's project set (deleted/renamed project, config edited to drop the project).

Common situations: Renaming or removing a project in config.toml while old cron job entries still reference the old name, partial config reload where jobs loaded but projects did not, or hand-editing a job's project field with a typo.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/e590e0aaf056f740. Report an issue: GitHub.