flipped-aurora/gin-vue-admin · error

存在同名CLI

Error message

存在同名CLI

What it means

CreateCli enforces unique CLI names: after the empty check it calls sysCliNameExists(ctx, name, 0), where 0 means "exclude no id" (full-table uniqueness for creation). If a record with the same trimmed name already exists, creation is rejected with this error. This prevents duplicate CLI identifiers that would be ambiguous to invoke.

Source

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

	"github.com/flipped-aurora/gin-vue-admin/server/global"
	sysModel "github.com/flipped-aurora/gin-vue-admin/server/model/system"
	autoModel "github.com/flipped-aurora/gin-vue-admin/server/plugin/ai/model"
	autoReq "github.com/flipped-aurora/gin-vue-admin/server/plugin/ai/model/request"
	autoRes "github.com/flipped-aurora/gin-vue-admin/server/plugin/ai/model/response"
	"gorm.io/gorm"
)

type cliService struct{}

func (s *cliService) CreateCli(ctx context.Context, req autoReq.CreateSysCliRequest) (autoModel.SysCli, error) {
	name := strings.TrimSpace(req.Name)
	if name == "" {
		return autoModel.SysCli{}, errors.New("cli名称不能为空")
	}
	if exists, err := s.sysCliNameExists(ctx, name, 0); err != nil {
		return autoModel.SysCli{}, err
	} else if exists {
		return autoModel.SysCli{}, errors.New("存在同名CLI")
	}
	entity := autoModel.SysCli{
		Name:             name,
		Command:          strings.TrimSpace(req.Command),
		DisplayName:      strings.TrimSpace(req.DisplayName),
		Version:          strings.TrimSpace(req.Version),
		Description:      strings.TrimSpace(req.Description),
		Status:           strings.TrimSpace(req.Status),
		AuthMode:         "jwt",
		SkillName:        strings.TrimSpace(req.SkillName),
		SkillDescription: strings.TrimSpace(req.SkillDescription),
		ScenariosJSON:    req.ScenariosJSON, // JSON 原文不裁剪
	}
	applySysCliDefaults(&entity)
	if err := global.GVA_DB.WithContext(ctx).Create(&entity).Error; err != nil {
		return autoModel.SysCli{}, err
	}
	return entity, nil

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Use the update/edit endpoint for the existing CLI instead of creating a new one
  2. Choose a different, unique name for the new CLI
  3. Check the CLI list first to confirm whether the record already exists before creating
  4. Disable the submit button after first click to avoid duplicate submissions

Example fix

// before: create on every save
await createCli({ name: 'my-cli' })
// after: update when the record exists
if (existingCliId) {
  await updateCli(existingCliId, { name: 'my-cli' })
} else {
  await createCli({ name: 'my-cli' })
}
Defensive patterns

Strategy: validation

Validate before calling

// before create, check uniqueness client-side when the list is available
if (cliList.some(c => c.name === name.trim())) {
  throw new Error(`CLI "${name}" already exists — use update instead`)
}

Try / catch

try {
  await createCli({ name })
} catch (e) {
  if (String(e.message).includes('存在同名CLI')) {
    // switch the dialog to edit mode for the existing record
    openEditForExisting(name)
  } else { throw e }
}

Prevention

When it happens

Trigger: Calling CreateCli with a name that already exists in the sys_cli table — e.g. resubmitting a form after a successful create, or two users/sessions creating the same CLI concurrently.

Common situations: Double-click/double-submit of the create form; importing or seeding CLIs that already exist; trying to "update" via the create endpoint; case or whitespace differences that trim to the same name.

Related errors


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