flipped-aurora/gin-vue-admin · error

apiId不能为空

Error message

apiId不能为空

What it means

AddCliApis validates each binding in req.Bindings: a binding whose ApiID is 0 (the zero value for uint) is rejected with this error because an API binding without an API id is meaningless. Valid ids are deduplicated via the seen map and collected into apiIDs for the existence check.

Source

Thrown at server/plugin/ai/service/sys_cli.go:138

	return res, nil
}

func (s *cliService) GetCliDetail(ctx context.Context, req autoReq.FindSysCliRequest) (autoRes.SysCliDetailResponse, error) {
	return s.getCliDetailByID(ctx, req.ID)
}

func (s *cliService) AddCliApis(ctx context.Context, req autoReq.AddSysCliApisRequest) (autoRes.SysCliDetailResponse, error) {
	if _, err := s.getSysCliByID(ctx, req.CliID); err != nil {
		return autoRes.SysCliDetailResponse{}, err
	}
	if len(req.Bindings) == 0 {
		return s.getCliDetailByID(ctx, req.CliID)
	}
	apiIDs := make([]uint, 0, len(req.Bindings))
	seen := make(map[uint]struct{}, len(req.Bindings))
	for _, binding := range req.Bindings {
		if binding.ApiID == 0 {
			return autoRes.SysCliDetailResponse{}, errors.New("apiId不能为空")
		}
		if _, ok := seen[binding.ApiID]; ok {
			continue
		}
		seen[binding.ApiID] = struct{}{}
		apiIDs = append(apiIDs, binding.ApiID)
	}
	if err := s.ensureApisExist(ctx, apiIDs); err != nil {
		return autoRes.SysCliDetailResponse{}, err
	}
	if err := global.GVA_DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		for _, item := range req.Bindings {
			var existing autoModel.SysCliApi
			err := tx.Unscoped().Where("cli_id = ? AND api_id = ?", req.CliID, item.ApiID).First(&existing).Error
			if errors.Is(err, gorm.ErrRecordNotFound) {
				entity := autoModel.SysCliApi{CliID: req.CliID, ApiID: item.ApiID, CommandName: strings.TrimSpace(item.CommandName), CommandDesc: strings.TrimSpace(item.CommandDesc), ParamsOverride: strings.TrimSpace(item.ParamsOverride), ApiBrief: strings.TrimSpace(item.ApiBrief), ResponseOverride: strings.TrimSpace(item.ResponseOverride), Enabled: item.Enabled, Sort: item.Sort}
				if err := tx.Create(&entity).Error; err != nil {
					return err

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Ensure every element of req.Bindings has a non-zero ApiID before calling
  2. Filter out bindings with ApiID == 0 client-side
  3. Fix JSON field names so ApiID actually deserializes
  4. Validate the payload with a quick loop before the service call

Example fix

// before
bindings := []autoReq.SysCliApiBinding{{Params: "{}"}, {ApiID: 3}}
cliService.AddCliApis(ctx, autoReq.AddSysCliApisRequest{CliID: 1, Bindings: bindings})
// after
valid := bindings[:0]
for _, b := range bindings {
    if b.ApiID != 0 { valid = append(valid, b) }
}
cliService.AddCliApis(ctx, autoReq.AddSysCliApisRequest{CliID: 1, Bindings: valid})
Defensive patterns

Strategy: validation

Validate before calling

for i, b := range req.Bindings {
    if b.ApiID == 0 {
        return fmt.Errorf("bindings[%d].apiId is required", i)
    }
}

Type guard

func allBindingsValid(bindings []autoReq.SysCliApiBinding) bool {
    for _, b := range bindings {
        if b.ApiID == 0 { return false }
    }
    return true
}

Try / catch

detail, err := cliService.AddCliApis(ctx, req)
if err != nil {
    if err.Error() == "apiId不能为空" {
        return fmt.Errorf("every binding needs an apiId; check rows with empty API selection")
    }
    return err
}

Prevention

When it happens

Trigger: Calling AddCliApis with a Bindings slice containing an element where ApiID is unset/zero, e.g. a binding that only carries other fields (params/order) but no ApiID, or a client that failed to populate the id.

Common situations: Frontend building binding rows from an API picker where the selection was cleared but the row kept; JSON payloads using a string key like "apiId" that does not match the Go field so it unmarshals to 0; batch scripts looping over partially populated records.

Related errors


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