SigNoz/signoz · error · errors.Error

CodeLicenseUnavailable

CodeLicenseUnavailable

Error message

a valid license is not available

What it means

parseGetErrorRequest requires the groupID query parameter when fetching a single error from the errors API; an empty/missing groupID yields 'groupID param cannot be empty from the query'. Used by getErrorFromErrorID, getNextPrevErrorIDs and getErrorFromGroupID handlers.

Source

Thrown at ee/modules/cloudintegration/implcloudintegration/module.go:66

		store:             store,
		dashboardModule:   dashboardModule,
		global:            global,
		zeus:              zeus,
		gateway:           gateway,
		licensing:         licensing,
		serviceAccount:    serviceAccount,
		cloudProvidersMap: cloudProvidersMap,
		config:            config,
	}, nil
}

// GetConnectionCredentials returns credentials required to generate connection artifact. eg. apiKey, ingestionKey etc.
// It will return creds it can deduce and return empty value for others.
func (module *module) GetConnectionCredentials(ctx context.Context, orgID valuer.UUID, provider cloudintegrationtypes.CloudProviderType) (*cloudintegrationtypes.Credentials, error) {
	// get license to get the deployment details
	license, err := module.licensing.GetActive(ctx, orgID)
	if err != nil {
		return nil, errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
	}

	// get deployment details from zeus, ignore error
	respBytes, _ := module.zeus.GetDeployment(ctx, license.Key)

	var signozAPIURL string

	if len(respBytes) > 0 {
		// parse deployment details, ignore error, if client is asking api url every time check for possible error
		deployment, _ := zeustypes.NewGettableDeployment(respBytes)
		if deployment != nil {
			signozAPIURL, _ = cloudintegrationtypes.GetSigNozAPIURLFromDeployment(deployment)
		}
	}

	// ignore error
	apiKey, _ := module.getOrCreateAPIKey(ctx, orgID, provider)

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Always include groupID=<groupID> (from the errors list response's groupID field) in the request
  2. Persist both errorID and groupID when building deep links
  3. Validate presence of groupID client-side before fetching error detail

Example fix

# before
curl '.../api/v1/errors/view?ts=1700000000000000000&errorID=abc'

# after
curl '.../api/v1/errors/view?ts=1700000000000000000&groupID=xyz&errorID=abc'
Defensive patterns

Strategy: validation

Validate before calling

groupID := r.URL.Query().Get("groupID")
if strings.TrimSpace(groupID) == "" {
	return errors.New("groupID is required; take it from the errors list response")
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: GET /api/v1/errors/{errorID-or-group} (or the next/prev endpoint) with a valid ts= timestamp but no groupID= parameter, or groupID= with an empty value.

Common situations: Frontend deep links losing the groupID query string on refresh; clients passing only errorID assuming it identifies the group; URL encoding bugs stripping empty params; API wrappers that omit optional-looking params.

Related errors


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