dapr/dapr · error

failed to join path for authorization endpoint: %w

Error message

failed to join path for authorization endpoint: %w

What it means

Dapr sentry's OIDC server constructor joins the configured PathPrefix with the authorization endpoint path '/authorize' using url.JoinPath. As with the sibling JWKS/discovery joins, the only failure mode is a base prefix that cannot be parsed as a URL reference — control characters, malformed percent-escapes, or a NUL byte. Valid path prefixes never produce this error.

Source

Thrown at pkg/sentry/server/oidc/oidc.go:154

	authorizeEndpoint := AuthorizationEndpoint
	if opts.PathPrefix != nil && *opts.PathPrefix != "/" {
		if before, ok := strings.CutSuffix(*opts.PathPrefix, "/"); ok {
			opts.PathPrefix = new(before)
		}

		var err error

		jwksEndpoint, err = url.JoinPath(*opts.PathPrefix, JWKSEndpoint)
		if err != nil {
			return nil, fmt.Errorf("failed to join path for JWKS endpoint: %w", err)
		}
		oidcEndpoint, err = url.JoinPath(*opts.PathPrefix, OIDCDiscoveryEndpoint)
		if err != nil {
			return nil, fmt.Errorf("failed to join path for OIDC discovery endpoint: %w", err)
		}
		authorizeEndpoint, err = url.JoinPath(*opts.PathPrefix, authorizeEndpoint)
		if err != nil {
			return nil, fmt.Errorf("failed to join path for authorization endpoint: %w", err)
		}

		log.Infof("Using path prefix %q for OIDC HTTP endpoints", *opts.PathPrefix)
	}

	return &Server{
		port:              opts.Port,
		listenAddress:     opts.ListenAddress,
		jwks:              opts.JWKS,
		htarget:           opts.Healthz.AddTarget("oidc-server"),
		jwksURI:           opts.JWKSURI,
		allowedHosts:      opts.AllowedHosts,
		tlsCertPath:       opts.TLSCertPath,
		tlsKeyPath:        opts.TLSKeyPath,
		jwtIssuer:         opts.JWTIssuer,
		pathPrefix:        opts.PathPrefix,
		authorizeEndpoint: authorizeEndpoint,
		jwksEndpoint:      jwksEndpoint,

View on GitHub (pinned to 74ad417027)

Solutions

  1. Dump the effective PathPrefix with %q (fmt.Sprintf("%q", *opts.PathPrefix)) and strip the offending characters at the source (env var, chart value, CLI flag)
  2. Validate the prefix once up front: reject anything matching [^A-Za-z0-9._~/-] before calling NewServer
  3. Set the prefix from a parsed issuer URL's .Path field rather than a raw string
  4. Add a regression test covering the exact prefix value your deployment pipeline produces

Example fix

// before
prefix := fmt.Sprintf("%s/%s", baseEnv, subEnv) // may embed '%zz' or '\n'
authorize, err := url.JoinPath(prefix, "/authorize")

// after
u, err := url.Parse(issuerURL)
if err != nil { return err }
prefix := u.Path // clean, decoded path
authorize, err := url.JoinPath(prefix, "/authorize")
Defensive patterns

Strategy: validation

Validate before calling

func checkEndpoints(prefix string) error {
	for _, ep := range []string{"/jwks.json", "/.well-known/openid-configuration", "/authorize"} {
		if _, err := url.JoinPath(prefix, ep); err != nil {
			return fmt.Errorf("prefix %q invalid for %s: %w", prefix, ep, err)
		}
	}
	return nil
}

Try / catch

if _, err := oidc.NewServer(opts); err != nil {
    var joinErr *url.Error // JoinPath errors surface via url.Parse
    if errors.As(err, &joinErr) || strings.Contains(err.Error(), "join path") {
        log.Fatalf("fix the issuer path prefix in config: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: PathPrefix option containing an unparseable substring (e.g. '/dapr%2', '/da\x00pr'), set while PathPrefix != nil and != '/'. Because the two preceding joins run first, this specific error surfaces only when those passed and this join's base is rejected.

Common situations: Issuer path built by string concatenation from multiple env vars where one carries a bad escape or trailing control character; configuration managed by Helm/Ansible templates inserting stray '%' or whitespace artifacts into the issuer URL.

Related errors


AI-assisted analysis of dapr/dapr@74ad417027 (2026-08-16). Data as JSON: /api/errors/6a1c10a86f89447a. Report an issue: GitHub.