goharbor/harbor · error · lib/errors.Error

BadRequestCode

BadRequestCode

Error message

cannot be empty

What it means

Label.Valid() (called from the POST/PUT /api/v2.0/labels and /api/v2.0/projects/{project_id}/labels handlers) rejects a label whose Name is empty. The check is len(l.Name) == 0, so a missing or whitespace-only-as-empty name fails; it maps to BadRequestCode (HTTP 400).

Source

Thrown at src/pkg/label/model/model.go:48

// Label holds information used for a label
type Label struct {
	ID           int64     `orm:"pk;auto;column(id)" json:"id"`
	Name         string    `orm:"column(name)" json:"name"`
	Description  string    `orm:"column(description)" json:"description"`
	Color        string    `orm:"column(color)" json:"color"`
	Level        string    `orm:"column(level)" json:"-"`
	Scope        string    `orm:"column(scope)" json:"scope"`
	ProjectID    int64     `orm:"column(project_id)" json:"project_id"`
	CreationTime time.Time `orm:"column(creation_time);auto_now_add" json:"creation_time"`
	UpdateTime   time.Time `orm:"column(update_time);auto_now" json:"update_time"`
	Deleted      bool      `orm:"column(deleted)" json:"deleted"`
}

// Valid ...
func (l *Label) Valid() error {
	if len(l.Name) == 0 {
		return errors.New("cannot be empty").WithCode(errors.BadRequestCode)
	}
	if len(l.Name) > 128 {
		return errors.New("max length is 128").WithCode(errors.BadRequestCode)
	}

	if l.Scope != common.LabelScopeGlobal && l.Scope != common.LabelScopeProject {
		return errors.New(nil).WithMessagef("invalid: %s", l.Scope).WithCode(errors.BadRequestCode)
	} else if l.Scope == common.LabelScopeProject && l.ProjectID <= 0 {
		return errors.New(nil).WithMessagef("invalid: %d", l.ProjectID).WithCode(errors.BadRequestCode)
	}
	return nil
}

// TableName ...
func (l *Label) TableName() string {
	return "harbor_label"
}

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Provide a non-empty name in the request body, e.g. {"name": "critical", "scope": "g"}.
  2. Validate/trim the name client-side before calling the API.
  3. If it comes from a template, assert the templating produced a non-empty value.

Example fix

# before
curl -X POST https://harbor/api/v2.0/labels -d '{"scope": "g"}'
# after
curl -X POST https://harbor/api/v2.0/labels -d '{"name": "critical", "scope": "g", "color": "#FFFFFF"}'
Defensive patterns

Strategy: validation

Validate before calling

function validateLabelPayload(l) {
  if (!l || typeof l.name !== 'string' || l.name.trim().length === 0)
    throw new Error('label name must be a non-empty string');
  return true;
}

Try / catch

On HTTP 400 from the labels API, log the request body minus secrets, fill the missing name field, and re-send; do not blind-retry unchanged.

Prevention

When it happens

Trigger: POST or PUT to the label APIs with the "name" field omitted, set to "", or an empty string after JSON decoding; also direct model.Valid() calls in Go code that build a Label without a Name.

Common situations: Automation templates with a placeholder label name never filled in; YAML/JSON config that drops the name key after templating; API clients with optional-name structs that serialize as empty.

Related errors


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