goharbor/harbor · error · lib/errors.Error

PRECONDITION

PRECONDITION

Error message

the policy %d is disabled

What it means

Thrown by the replication controller's Start() (src/controller/replication/execution.go:104) when a replication execution is requested for a policy whose Enabled flag is false. It is returned before any execution record or task is created. The PRECONDITION code maps to HTTP 412, telling the caller the policy must be enabled before it can run.

Source

Thrown at src/controller/replication/execution.go:104

		wp:         lib.NewWorkerPool(10),
	}
}

type controller struct {
	repMgr     replication.Manager
	execMgr    task.ExecutionManager
	taskMgr    task.Manager
	regMgr     reg.Manager
	scheduler  scheduler.Scheduler
	flowCtl    flow.Controller
	ormCreator orm.Creator
	wp         *lib.WorkerPool
}

func (c *controller) Start(ctx context.Context, policy *replicationmodel.Policy, resource *model.Resource, trigger string) (int64, error) {
	logger := log.GetLogger(ctx)
	if !policy.Enabled {
		return 0, errors.New(nil).WithCode(errors.PreconditionCode).
			WithMessagef("the policy %d is disabled", policy.ID)
	}
	// create an execution record
	extra := make(map[string]any)
	if op := operator.FromContext(ctx); op != "" {
		extra["operator"] = op
	}

	var count int64
	// If running executions are found, skip the current execution and mark it as error.
	if policy.SingleActiveReplication {
		var err error
		count, err = c.execMgr.Count(ctx, &q.Query{
			Keywords: map[string]any{
				"VendorType": job.ReplicationVendorType,
				"VendorID":   policy.ID,
				"Status":     job.RunningStatus.String(),
			},

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Enable the policy first: PUT /api/v2.0/replication/policies/{id} with {"enabled": true}, then retry the execution request
  2. Fetch the policy immediately before starting and verify enabled=true, or re-fetch on 412 and retry once
  3. Fix automation scripts that hard-code policy IDs of policies that were later disabled

Example fix

// before
POST /api/v2.0/replication/executions
{"policy_id": 7}   // 412: the policy 7 is disabled

// after
PUT /api/v2.0/replication/policies/7
{"enabled": true}

POST /api/v2.0/replication/executions
{"policy_id": 7}
Defensive patterns

Strategy: validation

Validate before calling

policy, err := apiClient.GetReplicationPolicy(policyID)
if err != nil {
    return err
}
if !policy.Enabled {
    // enable first: PUT /replication/policies/%d with {"enabled": true}
    return fmt.Errorf("policy %d disabled; enable before starting", policyID)
}
return apiClient.StartReplication(policyID)

Type guard

func isPolicyDisabledErr(err error) bool {
    return errors.IsErr(err, errors.PreconditionCode) &&
        strings.Contains(err.Error(), "is disabled")
}

Try / catch

if _, err := replicationCtl.Start(ctx, policy, res, trigger); err != nil {
    if errors.IsErr(err, errors.PreconditionCode) && strings.Contains(err.Error(), "is disabled") {
        // enable policy, retry once
    }
    return err
}

Prevention

When it happens

Trigger: POST /api/v2.0/replication/executions with {"policy_id": N} where policy N has enabled=false; or calling replication.Controller.Start(ctx, policy, ...) with a policy fetched before another admin disabled it.

Common situations: Triggering a replication manually from automation/CI that assumes the policy is active; a policy disabled by a retention/cleanup script or another administrator; UI user clicking 'Replicate' on a stopped policy; race where the policy was disabled between fetch and start.

Related errors


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