goharbor/harbor · error · github.com/goharbor/harbor/src/lib/errors.Error

NOT_FOUND

NOT_FOUND

Error message

webhook task %d not found

What it means

The webhook controller's GetTask (src/controller/webhook/controller.go:148) lists tasks by ID filtered to webhook vendor types; zero matches returns NOT_FOUND (HTTP 404). GetTaskLog raises the same error because it first verifies the task exists and belongs to a webhook.

Source

Thrown at src/controller/webhook/controller.go:148

	return c.taskMgr.Count(ctx, buildTaskQuery(execID, query))
}

func (c *controller) ListTasks(ctx context.Context, execID int64, query *q.Query) ([]*task.Task, error) {
	return c.taskMgr.List(ctx, buildTaskQuery(execID, query))
}

func (c *controller) GetTask(ctx context.Context, taskID int64) (*task.Task, error) {
	query := q.New(q.KeyWords{
		"id":          taskID,
		"vendor_type": webhookJobVendors,
	})
	tasks, err := c.taskMgr.List(ctx, query)
	if err != nil {
		return nil, err
	}

	if len(tasks) == 0 {
		return nil, errors.New(nil).WithCode(errors.NotFoundCode).
			WithMessagef("webhook task %d not found", taskID)
	}
	return tasks[0], nil
}

func (c *controller) GetTaskLog(ctx context.Context, taskID int64) ([]byte, error) {
	// ensure the webhook task exist
	_, err := c.GetTask(ctx, taskID)
	if err != nil {
		return nil, err
	}

	return c.taskMgr.GetLog(ctx, taskID)
}

func buildExecutionQuery(policyID int64, query *q.Query) *q.Query {
	query = q.MustClone(query)
	query.Keywords["vendor_type"] = webhookJobVendors

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. List tasks for the execution first and use an ID from that list
  2. Confirm the ID is a webhook task ID, not an execution ID or a replication task ID
  3. Treat 404 as terminal - the task log is gone; enable webhook debug logging earlier next time

Example fix

// before
log, err := webhookCtl.GetTaskLog(ctx, 888)  // 404

// after
tasks, _ := webhookCtl.ListTasks(ctx, q.New(q.KeyWords{"ExecutionID": execID}))
for _, t := range tasks {
    log, err := webhookCtl.GetTaskLog(ctx, t.ID)
    ...
}
Defensive patterns

Strategy: validation

Validate before calling

tasks, err := webhookCtl.ListTasks(ctx, q.New(q.KeyWords{\"ExecutionID\": execID}))
if err != nil { return err }
for _, t := range tasks {
    if t.ID == taskID {
        // safe to fetch log
    }
}

Type guard

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

Try / catch

log, err := webhookCtl.GetTaskLog(ctx, taskID)
if err != nil {
    if errors.IsNotFoundErr(err) {
        // task of another vendor type or pruned; stop and report
    }
    return err
}

Prevention

When it happens

Trigger: GET webhook task or task-log endpoints with a task ID that doesn't exist, belongs to another job vendor type (replication, scan, GC), or was cleaned up after its retention window.

Common situations: Dashboards caching task IDs from old webhook executions; passing the webhook execution ID instead of the task ID; task records pruned by jobservice log cleanup.

Related errors


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