flipped-aurora/gin-vue-admin · error

缺少任务 ID

Error message

缺少任务 ID

What it means

UpdateTimedTask throws "缺少任务 ID" when SysTimedTask.ID is zero. Updates are keyed on the primary key, so an update without an ID is ambiguous and rejected before validation or persistence.

Source

Thrown at server/service/system/sys_timed_task.go:144

// CreateTimedTask 创建并按 enabled 调度
func (s *TimedTaskService) CreateTimedTask(ctx context.Context, t *system.SysTimedTask) error {
	if err := s.validateTask(t); err != nil {
		return err
	}
	if err := s.checkNameUnique(ctx, t.Name, 0); err != nil {
		return err
	}
	if err := global.GVA_DB.WithContext(ctx).Create(t).Error; err != nil {
		return err
	}
	return s.ScheduleTask(*t)
}

// UpdateTimedTask 更新并重新调度。Select 显式列 + Updates:
// 允许 enabled=false 等零值写入, 同时不碰 created_at/deleted_at。
func (s *TimedTaskService) UpdateTimedTask(ctx context.Context, t *system.SysTimedTask) error {
	if t.ID == 0 {
		return errors.New("缺少任务 ID")
	}
	if err := s.validateTask(t); err != nil {
		return err
	}
	if err := s.checkNameUnique(ctx, t.Name, t.ID); err != nil {
		return err
	}
	err := global.GVA_DB.WithContext(ctx).Model(&system.SysTimedTask{}).Where("id = ?", t.ID).
		Select("name", "description", "spec", "with_seconds", "executor_type", "method_name",
			"params", "http_url", "http_method", "http_header", "http_body", "http_allow_private", "enabled").
		Updates(t).Error
	if err != nil {
		return err
	}
	return s.ScheduleTask(*t)
}

// DeleteTimedTask 先移出调度再软删

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Populate t.ID with the existing record's primary key before calling UpdateTimedTask.
  2. Ensure the request body includes the numeric id field matching the binding tag.
  3. If the id arrives as a string, convert to uint client-side or fix the JSON type.
  4. Verify the list/detail API actually returns and the frontend retains the id field.

Example fix

// before
svc.UpdateTimedTask(ctx, &system.SysTimedTask{Name: "renamed"}) // ID == 0

// after
svc.UpdateTimedTask(ctx, &system.SysTimedTask{ID: existing.ID, Name: "renamed", Spec: existing.Spec, ExecutorType: existing.ExecutorType})
Defensive patterns

Strategy: validation

Validate before calling

if task.ID == 0 {
    return errors.New("cannot update a timed task without a numeric ID")
}
// proceed with svc.UpdateTimedTask(ctx, task)

Type guard

func hasID(t system.SysTimedTask) bool { return t.ID != 0 }

Try / catch

if err := svc.UpdateTimedTask(ctx, task); err != nil {
    if strings.Contains(err.Error(), "缺少任务 ID") {
        http.Error(w, "id is required for update", http.StatusBadRequest)
        return
    }
    http.Error(w, err.Error(), http.StatusInternalServerError)
}

Prevention

When it happens

Trigger: Calling UpdateTimedTask with a struct built client-side but never populated with the record's ID; binding a PUT body that omits the id field; using a create-style payload (no id) on the update endpoint.

Common situations: Frontend editing a task fetched via a list that didn't select id; int/uint type mismatch so JSON id decodes to 0 (e.g. string "12" into a uint field); new form rows submitted as updates.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/6f21c6f547e9ac03. Report an issue: GitHub.