bytebase/bytebase · warning

CodeResourceExhausted

CodeResourceExhausted

Error message

new VCS user would exceed the license user limit; increase the license user limit or wait for inactive VCS users to age out of the %d-day window

What it means

touchVCSProviderUser returns CodeResourceExhausted when adding/refreshing a new VCS provider user would push the workspace over its license user limit, counting only users active within the rolling window (vcsProviderUserActiveWindow). The message directs the operator to raise the limit or let inactive VCS users age out.

Source

Thrown at backend/api/v1/release_service_check.go:243

func (s *ReleaseService) touchVCSProviderUser(ctx context.Context, workspaceID string, vcsUser *v1pb.VCSUser) error {
	if vcsUser == nil {
		return nil
	}
	userName := truncateVCSProviderUserMetadata(vcsUser.GetUserName())
	displayName := truncateVCSProviderUserMetadata(vcsUser.GetDisplayName())
	ok, err := s.store.TouchVCSProviderUser(ctx, workspaceID, &store.VCSProviderUserMessage{
		VCSType: vcsUser.GetVcsType(),
		UserID:  vcsUser.GetUserId(),
		Payload: &storepb.VCSProviderUserPayload{
			UserName:    userName,
			DisplayName: displayName,
		},
	}, vcsProviderUserActiveWindow, s.license.GetUserLimit(ctx, workspaceID))
	if err != nil {
		return connect.NewError(connect.CodeInternal, errors.Wrap(err, "failed to touch VCS provider user"))
	}
	if !ok {
		return connect.NewError(connect.CodeResourceExhausted, errors.Errorf("new VCS user would exceed the license user limit; increase the license user limit or wait for inactive VCS users to age out of the %d-day window", vcsProviderUserActiveWindowDays))
	}
	return nil
}

const maxVCSProviderUserFieldLength = 256

func validateVCSProviderUser(vcsUser *v1pb.VCSUser) error {
	if vcsUser == nil {
		return nil
	}
	if vcsUser.GetVcsType() == v1pb.VCSType_VCS_TYPE_UNSPECIFIED {
		return connect.NewError(connect.CodeInvalidArgument, errors.New("vcs_user.vcs_type is required"))
	}
	if _, ok := v1pb.VCSType_name[int32(vcsUser.GetVcsType())]; !ok {
		return connect.NewError(connect.CodeInvalidArgument, errors.Errorf("vcs_user.vcs_type %d is invalid", vcsUser.GetVcsType()))
	}
	if vcsUser.GetUserId() == "" {
		return connect.NewError(connect.CodeInvalidArgument, errors.New("vcs_user.user_id is required"))

View on GitHub (pinned to 1870550677)

Solutions

  1. Increase the license user limit for the workspace.
  2. Wait vcsProviderUserActiveWindow days for inactive VCS users to age out, then retry.
  3. Deactivate or clean up VCS user records for departed developers if tooling permits.
  4. Reuse an existing active vcs_user identity instead of introducing a new one.
Defensive patterns

Strategy: fallback

Validate before calling

activeCount := countActiveVCSUsers(workspaceID, window)
if activeCount >= licenseUserLimit(workspaceID) {
    return errors.New("license user limit reached before sending vcs_user")
}

Try / catch

if connect.CodeOf(err) == connect.CodeResourceExhausted {
    // alert operator to raise license limit or reuse existing identity
}

Prevention

When it happens

Trigger: A VCS-triggered CheckRelease introduces a vcs_user whose user_id has no active record, and active VCS user count already equals license.GetUserLimit for the workspace.

Common situations: Growing team connecting via GitLab/GitHub webhooks on a fixed-seat license; long-lived seat allocation consumed by departed developers' VCS identities still inside the active window; evaluating Bytebase on a trial/free license in a busy org.

Related errors


AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06). Data as JSON: /api/errors/8b0ce993d3b55594. Report an issue: GitHub.