netbirdio/netbird · error

identity provider issuer must be a valid URL

Error message

identity provider issuer must be a valid URL

What it means

Sentinel error types.ErrIdentityProviderIssuerInvalid (management/server/types/identity_provider.go:14), returned by IdentityProvider.Validate whenever Issuer is non-empty but url.Parse fails or the parsed URL has no scheme or host. The check accepts any parseable absolute URL, so failure almost always means a missing scheme (https://) or a malformed host.

Source

Thrown at management/server/types/identity_provider.go:14

package types

import (
	"errors"
	"net/url"
)

// Identity provider validation errors
var (
	ErrIdentityProviderNameRequired      = errors.New("identity provider name is required")
	ErrIdentityProviderTypeRequired      = errors.New("identity provider type is required")
	ErrIdentityProviderTypeUnsupported   = errors.New("unsupported identity provider type")
	ErrIdentityProviderIssuerRequired    = errors.New("identity provider issuer is required")
	ErrIdentityProviderIssuerInvalid     = errors.New("identity provider issuer must be a valid URL")
	ErrIdentityProviderIssuerUnreachable = errors.New("identity provider issuer is unreachable")
	ErrIdentityProviderIssuerMismatch    = errors.New("identity provider issuer does not match the issuer returned by the provider")
	ErrIdentityProviderClientIDRequired  = errors.New("identity provider client ID is required")
)

// IdentityProviderType is the type of identity provider
type IdentityProviderType string

const (
	// IdentityProviderTypeOIDC is a generic OIDC identity provider
	IdentityProviderTypeOIDC IdentityProviderType = "oidc"
	// IdentityProviderTypeZitadel is the Zitadel identity provider
	IdentityProviderTypeZitadel IdentityProviderType = "zitadel"
	// IdentityProviderTypeEntra is the Microsoft Entra (Azure AD) identity provider
	IdentityProviderTypeEntra IdentityProviderType = "entra"
	// IdentityProviderTypeGoogle is the Google identity provider
	IdentityProviderTypeGoogle IdentityProviderType = "google"
	// IdentityProviderTypeOkta is the Okta identity provider

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Send a full absolute URL including scheme and host, e.g. https://auth.example.com/realms/netbird
  2. Trim whitespace and verify the value with url.Parse client-side before submitting

Example fix

// before
idp.Issuer = "auth.example.com/realms/netbird"

// after
idp.Issuer = "https://auth.example.com/realms/netbird"
Defensive patterns

Strategy: validation

Validate before calling

func isValidIssuerURL(issuer string) bool {
    if issuer == "" { return true } // emptiness is checked separately
    u, err := url.Parse(strings.TrimSpace(issuer))
    return err == nil && u.Scheme != "" && u.Host != ""
}

if !isValidIssuerURL(idp.Issuer) {
    return types.ErrIdentityProviderIssuerInvalid
}

Try / catch

if err := idp.Validate(); err != nil {
    if errors.Is(err, types.ErrIdentityProviderIssuerInvalid) {
        // normalize: trim spaces, prepend https:// if missing, re-validate
    }
    return err
}

Prevention

When it happens

Trigger: Saving an IdP with issuer like "auth.example.com/realms/nb" (no scheme), "https:///path" (no host), or a string containing control characters that url.Parse rejects.

Common situations: Operators pasting the issuer without https://; Terraform variables that strip the scheme; trailing whitespace or copy artifacts from web consoles; issuer taken from a metadata endpoint that returns a path-only value.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/521075ac1bc25ffe. Report an issue: GitHub.