SigNoz/signoz · error · errors.Error

CodeLicenseUnavailable

CodeLicenseUnavailable

Error message

a valid license is not available

What it means

parseMetricsDuration accepts either a float interpreted as seconds or a Prometheus-style duration string (prommodel.ParseDuration: '5m', '1h30m', '1d'); if both fail it returns 'cannot parse %q to a valid duration'. Used for step and similar parameters of the metrics query APIs.

Source

Thrown at ee/authz/openfgaauthz/provider.go:181

	return provider.pkgAuthzService.CreateManagedRoles(ctx, orgID, managedRoles)
}

func (provider *provider) CreateManagedUserRoleTransactions(ctx context.Context, orgID valuer.UUID, userID valuer.UUID) error {
	tuples := make([]*openfgav1.TupleKey, 0)

	grantTuples := provider.getManagedRoleGrantTuples(orgID, userID)
	tuples = append(tuples, grantTuples...)

	managedRoleTuples := provider.getManagedRoleTransactionTuples(orgID)
	tuples = append(tuples, managedRoleTuples...)

	return provider.Write(ctx, tuples, nil)
}

func (provider *provider) Create(ctx context.Context, orgID valuer.UUID, role *authtypes.Role) error {
	_, err := provider.licensing.GetActive(ctx, orgID)
	if err != nil {
		return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
	}

	existingRole, err := provider.GetByOrgIDAndName(ctx, orgID, role.Name)
	if err != nil && !errors.Asc(err, authtypes.ErrCodeRoleNotFound) {
		return err
	}

	if existingRole != nil {
		return errors.Newf(errors.TypeAlreadyExists, authtypes.ErrCodeRoleAlreadyExists, "role with name: %s already exists", existingRole.Name)
	}

	tuples, err := authtypes.NewTuplesFromTransactionGroups(role.Name, orgID, role.TransactionGroups)
	if err != nil {
		return err
	}

	err = provider.Write(ctx, tuples, nil)
	if err != nil {

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Use Prometheus duration syntax: '10s', '5m', '1h', '1d' or combinations like '1h30m'
  2. Or send a plain number meaning seconds ('60')
  3. Sanitize whitespace and validate with a regex like ^[0-9]+(ms|s|m|h|d)$ or ^[0-9.]+$ client-side

Example fix

# before
curl '.../api/v1/query_range?step=PT5M'

# after
curl '.../api/v1/query_range?step=5m'
Defensive patterns

Strategy: validation

Validate before calling

var stepRe = regexp.MustCompile(`^([0-9]+(\.[0-9]+)?|([0-9]+(ms|s|m|h|d))+)$`)
if !stepRe.MatchString(stepParam) { /* reject before request */ }

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Calling queryRangeMetrics/queryMetrics with a step value like '60s ' (trailing space), '1 hr' (space inside), ISO durations ('PT1H'), or a non-numeric string such as 'hour' — none parse as float or Prometheus duration.

Common situations: Copy-pasting ISO-8601 durations from other systems; frontend formatting bugs inserting spaces or unicode; assuming Go's time.ParseDuration syntax ('1h30m') where only Prometheus units (no 'us', different day handling) are supported.

Related errors


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/3b69bb5ed949a9fb. Report an issue: GitHub.