goharbor/harbor · error · lib/errors.Error

NOT_FOUND

NOT_FOUND

Error message

replication execution %d not found

What it means

Returned by the replication controller's GetExecution (src/controller/replication/execution.go:242) when listing executions by ID and VendorType=REPLICATION returns zero rows. The vendor-type filter means an execution ID belonging to another job type (e.g. garbage collection, scan) will also report not found. Maps to HTTP 404.

Source

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

	if value, exist := query.Keywords["policy_id"]; exist {
		query.Keywords["VendorID"] = value
		delete(query.Keywords, "policy_id")
	}
	return query
}

func (c *controller) GetExecution(ctx context.Context, id int64) (*Execution, error) {
	execs, err := c.execMgr.List(ctx, &q.Query{
		Keywords: map[string]any{
			"ID":         id,
			"VendorType": job.ReplicationVendorType,
		},
	})
	if err != nil {
		return nil, err
	}
	if len(execs) == 0 {
		return nil, errors.New(nil).WithCode(errors.NotFoundCode).
			WithMessagef("replication execution %d not found", id)
	}
	return convertExecution(execs[0]), nil
}

func (c *controller) TaskCount(ctx context.Context, query *q.Query) (int64, error) {
	query = q.MustClone(query)
	query.Keywords["VendorType"] = job.ReplicationVendorType
	return c.taskMgr.Count(ctx, query)
}

func (c *controller) ListTasks(ctx context.Context, query *q.Query) ([]*Task, error) {
	query = q.MustClone(query)
	query.Keywords["VendorType"] = job.ReplicationVendorType
	tks, err := c.taskMgr.List(ctx, query)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Verify the ID by listing executions first: GET /api/v2.0/replication/executions and match the ID
  2. Confirm you queried the right resource type (execution vs task) and the right API (replication vs webhook executions)
  3. Treat 404 as terminal for retry loops - do not keep retrying a deleted execution

Example fix

// before
exec, err := replicationCtl.GetExecution(ctx, 999999)
// 404: replication execution 999999 not found

// after
execs, err := apiClient.ListReplicationExecutions(nil)
if idExists(execs, 999999) {
    exec, err = apiClient.GetReplicationExecution(999999)
}
Defensive patterns

Strategy: validation

Validate before calling

execs, err := apiClient.ListReplicationExecutions(&q.Query{Keywords: map[string]any{"PolicyID": policyID}})
if err != nil { return err }
found := false
for _, e := range execs {
    if e.ID == wantID { found = true; break }
}
if !found { return fmt.Errorf("execution %d not in replication list", wantID) }

Type guard

func isExecutionNotFound(err error) bool {
    return errors.IsNotFoundErr(err) || errors.IsErr(err, errors.NotFoundCode)
}

Try / catch

exec, err := replicationCtl.GetExecution(ctx, id)
if err != nil {
    if errors.IsNotFoundErr(err) {
        // remove from UI cache; do not retry
    }
    return err
}

Prevention

When it happens

Trigger: GET /api/v2.0/replication/executions/{id} with an ID that does not exist, belongs to a non-replication vendor type, or was purged; calling controller.GetExecution(ctx, id) after the execution record was cleaned up.

Common situations: Stale execution ID held in a dashboard or script; paging through executions while GC deletes old records; passing a task ID where an execution ID was expected; typo'd or truncated ID from logs.

Related errors


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