goharbor/harbor · error

missing job name in job stats

Error message

missing job name in job stats

What it means

job.Stats.Validate (src/jobservice/job/models.go:126) requires Info.JobName to be non-empty; the name maps a running execution back to its registered job implementation. Note: the identical message is reused a few lines later for an empty JobKind (a Harbor copy-paste), so the message alone does not prove which field is missing.

Source

Thrown at src/jobservice/job/models.go:126

// SimpleStatusChange only keeps job ID and the target status
type SimpleStatusChange struct {
	JobID        string `json:"job_id"`
	TargetStatus string `json:"target_status"`
	Revision     int64  `json:"revision"`
}

// Validate the job stats
func (st *Stats) Validate() error {
	if st.Info == nil {
		return errors.New("nil stats body")
	}

	if utils.IsEmptyStr(st.Info.JobID) {
		return errors.New("missing job ID in job stats")
	}

	if utils.IsEmptyStr(st.Info.JobName) {
		return errors.New("missing job name in job stats")
	}

	if utils.IsEmptyStr(st.Info.JobKind) {
		return errors.New("missing job name in job stats")
	}

	if st.Info.JobKind != KindGeneric &&
		st.Info.JobKind != KindPeriodic &&
		st.Info.JobKind != KindScheduled {
		return errors.Errorf("job kind is not supported: %s", st.Info.JobKind)
	}

	status := Status(st.Info.Status)
	if err := status.Validate(); err != nil {
		return err
	}

	if st.Info.JobKind == KindPeriodic {

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Populate JobName with the registered job name when creating stats
  2. If JobName is present, check Info.JobKind — the same error text covers it
  3. Inspect the raw JSON payload to see which field is actually absent

Example fix

// before
Info: &job.StatsInfo{JobID: "ju-1234"}
// after
Info: &job.StatsInfo{
    JobID:   "ju-1234",
    JobName: "GARBAGE_COLLECTION",
    JobKind: job.KindGeneric,
}
Defensive patterns

Strategy: type-guard

Validate before calling

if err := st.Validate(); err != nil {
    return err // rejects empty JobName AND empty JobKind with the same text
}

Type guard

func hasStatsJobName(st *job.Stats) bool {
    return st != nil && st.Info != nil && strings.TrimSpace(st.Info.JobName) != "" && strings.TrimSpace(st.Info.JobKind) != ""
}

Prevention

When it happens

Trigger: Stats written with Info.JobName empty; deserializing a payload whose info.job_name is missing. If JobName is actually set, the same text fires for an empty info.job_kind instead.

Common situations: Producers copying stats structs without the name; refactored serializers renaming 'job_name'; fixtures trimmed for tests.

Related errors


AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16). Data as JSON: /api/errors/c9fe55bfe04c262a. Report an issue: GitHub.