goharbor/harbor · error · badRequestError

10013

10013

Error message

empty job ID

What it means

basicController.GetJob (src/jobservice/core/controller.go:105) rejects an empty job ID before querying the manager, wrapping it with errs.BadRequestError — code 10013, the job service's equivalent of HTTP 400. It signals a client bug: the identifier never made it into the call.

Source

Thrown at src/jobservice/core/controller.go:105

			req.Job.Metadata.IsUnique,
			req.Job.StatusHook,
		)
	}

	// Save job stats
	if err == nil {
		if err := bc.manager.SaveJob(res); err != nil {
			return nil, err
		}
	}

	return
}

// GetJob is implementation of same method in core interface.
func (bc *basicController) GetJob(jobID string) (*job.Stats, error) {
	if utils.IsEmptyStr(jobID) {
		return nil, errs.BadRequestError(errors.New("empty job ID"))
	}

	return bc.manager.GetJob(jobID)
}

// StopJob is implementation of same method in core interface.
func (bc *basicController) StopJob(jobID string) error {
	if utils.IsEmptyStr(jobID) {
		return errs.BadRequestError(errors.New("empty job ID"))
	}

	return bc.backendWorker.StopJob(jobID)
}

// RetryJob is implementation of same method in core interface.
func (bc *basicController) RetryJob(jobID string) error {
	if utils.IsEmptyStr(jobID) {
		return errs.BadRequestError(errors.New("empty job ID"))

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Guard the call site: fail fast when jobID is empty
  2. Trace the empty value upstream — usually a failed submission or a deserialization field-name mismatch
  3. Log the raw request when it happens to catch routing/client bugs

Example fix

// before
stats, err := ctrl.GetJob(jobID)
// after
if utils.IsEmptyStr(jobID) {
    return nil, fmt.Errorf("job ID is required to fetch job stats")
}
stats, err := ctrl.GetJob(jobID)
Defensive patterns

Strategy: validation

Validate before calling

func requireJobID(jobID string) error {
    if strings.TrimSpace(jobID) == "" {
        return fmt.Errorf("job ID must not be empty")
    }
    return nil
}

Type guard

func isNonEmptyJobID(id string) bool {
    return strings.TrimSpace(id) != ""
}

Try / catch

stats, err := ctrl.GetJob(jobID)
if err != nil {
    if errs.IsBadRequestError(err) { // code 10013
        // client error: surface 400, do not retry
    }
    // otherwise treat as server-side and handle normally
}

Prevention

When it happens

Trigger: Calling core.Controller.GetJob with '' or a whitespace-only string; via REST, GET /api/v2.0/jobservice/jobs/{job_id} where the path parameter resolves to empty (collapsed double slash, malformed client URL).

Common situations: Client submits a job, ignores the error in the submit response, then queries with a never-assigned variable; JSON field mismatch (job_id vs jobId) leaves the value empty; URL assembled by concatenation with a missing segment.

Related errors


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