v2rayA/v2rayA · error

tag '%s' already exists

Error message

tag '%s' already exists

What it means

PostCustomInbound rejects creation of a custom inbound whose Tag matches an existing inbound's tag. Tags are unique identifiers used by the core to reference inbounds, so duplicates would create ambiguous references. The check iterates all configured custom inbounds before saving.

Source

Thrown at service/server/controller/customInbound.go:92

		hardcodeReplacement := regexp.MustCompile(`\$\$.+?\$\$`)
		for i := range lines {
			hardcodes := hardcodeReplacement.FindAllString(lines[i], -1)
			for _, hardcode := range hardcodes {
				lines[i] = strings.Replace(lines[i], hardcode, "", 1)
			}
		}
		_, err := RoutingA.Parse(strings.Join(lines, "\n"))
		if err != nil {
			common.ResponseError(ctx, logError(fmt.Errorf("invalid RoutingA rules: %w", err)))
			return
		}
	}

	inbounds := configure.GetCustomInbounds()
	// check duplicate tag and port
	for _, existing := range inbounds {
		if existing.Tag == ci.Tag {
			common.ResponseError(ctx, logError(fmt.Errorf("tag '%s' already exists", ci.Tag)))
			return
		}
		if existing.Port == ci.Port {
			common.ResponseError(ctx, logError(fmt.Errorf("port %d is already in use by '%s'", ci.Port, existing.Tag)))
			return
		}
	}
	inbounds = append(inbounds, ci)
	if err := configure.SetCustomInbounds(inbounds); err != nil {
		common.ResponseError(ctx, logError(err))
		return
	}
	common.ResponseSuccess(ctx, gin.H{"inbounds": inbounds})
}

func DeleteCustomInbound(ctx *gin.Context) {
	var req struct {
		Tag string `json:"tag"`

View on GitHub (pinned to 71e5442fc5)

Solutions

  1. Choose a different, unique tag for the new inbound
  2. List existing inbounds first and pick an unused tag
  3. Delete the old inbound with the same tag if it is no longer needed
  4. Make the client idempotent: check for existence before POSTing

Example fix

// before
{ "tag": "inbound-1", "port": 1080, ... }
// after
{ "tag": "inbound-2", "port": 1080, ... }
Defensive patterns

Strategy: validation

Validate before calling

inbounds := configure.GetCustomInbounds()
if inbounds.Any(func(i configure.CustomInbound) bool { return i.Tag == newTag }) {
	return fmt.Errorf("tag %q already exists", newTag)
}

Prevention

When it happens

Trigger: POST to the custom inbound API with a 'tag' field identical to any existing custom inbound's tag.

Common situations: Re-submitting a form after a partial failure; client retry duplicating a successfully created inbound; copying an inbound definition and forgetting to change the tag.

Related errors


AI-assisted analysis of v2rayA/v2rayA@71e5442fc5 (2026-09-05). Data as JSON: /api/errors/173ee51c5d7a9aac. Report an issue: GitHub.