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
- Guard the call site: fail fast when jobID is empty
- Trace the empty value upstream — usually a failed submission or a deserialization field-name mismatch
- 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
- Persist the job ID from every successful submission before making follow-up calls
- Validate identifiers at the API boundary, not deep in handlers
- Treat code 10013 as non-retryable — retrying an empty ID never succeeds
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
- invalid json request
- File {} not exist
- Internal dir for tls {} not exist
- Port number in metrics is not valid
- Jaeger Colector Endpoint or Agent host not set, must set one
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/b70ef8ed6f536299.
Report an issue: GitHub.