fatedier/frp · error

failed to read OIDC CA certificate file %q: %w

Error message

failed to read OIDC CA certificate file %q: %w

What it means

The OIDC auth setup tried to load the configured trusted CA file (oidc.trustedCAFile) with os.ReadFile and the read failed. The path is used verbatim, so this is a classic file-access failure wrapped with the offending path in the message.

Source

Thrown at pkg/auth/oidc.go:51

	"github.com/fatedier/frp/pkg/config/v1/validation"
	"github.com/fatedier/frp/pkg/msg"
)

// createOIDCHTTPClient creates an HTTP client with custom TLS and proxy configuration for OIDC token requests
func createOIDCHTTPClient(trustedCAFile string, insecureSkipVerify bool, proxyURL string) (*http.Client, error) {
	// Clone the default transport to get all reasonable defaults
	transport := http.DefaultTransport.(*http.Transport).Clone()

	// Configure TLS settings
	if trustedCAFile != "" || insecureSkipVerify {
		tlsConfig := &tls.Config{
			InsecureSkipVerify: insecureSkipVerify,
		}

		if trustedCAFile != "" && !insecureSkipVerify {
			caCert, err := os.ReadFile(trustedCAFile)
			if err != nil {
				return nil, fmt.Errorf("failed to read OIDC CA certificate file %q: %w", trustedCAFile, err)
			}

			caCertPool := x509.NewCertPool()
			if !caCertPool.AppendCertsFromPEM(caCert) {
				return nil, fmt.Errorf("failed to parse OIDC CA certificate from file %q", trustedCAFile)
			}

			tlsConfig.RootCAs = caCertPool
		}
		transport.TLSClientConfig = tlsConfig
	}

	// Configure proxy settings
	if proxyURL != "" {
		parsedURL, err := url.Parse(proxyURL)
		if err != nil {
			return nil, fmt.Errorf("failed to parse OIDC proxy URL %q: %w", proxyURL, err)
		}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Check the exact path in the error message with ls -l as the service user; fix existence and read permission.
  2. Use an absolute path for oidc.trustedCAFile to avoid working-directory ambiguity.
  3. In containers, mount the CA file at the configured path.
  4. If the OIDC provider uses a public CA, remove oidc.trustedCAFile and rely on system roots.

Example fix

# before (frps.toml)
[auth]
method = "oidc"
[auth.oidc]
trustedCAFile = "ca.pem"   # relative, not next to binary

# after
[auth]
method = "oidc"
[auth.oidc]
trustedCAFile = "/etc/frp/oidc-ca.pem"
Defensive patterns

Strategy: validation

Validate before calling

if cfg.Auth.OIDC.TrustedCAFile != "" {
    if _, err := os.Stat(cfg.Auth.OIDC.TrustedCAFile); err != nil {
        return fmt.Errorf("OIDC CA file missing or unreadable: %w", err)
    }
}

Prevention

When it happens

Trigger: oidc.trustedCAFile set to a path that doesn't exist, is a directory, or is unreadable by the process user; relative paths are resolved against the process working directory rather than the config location.

Common situations: CA file not shipped to the host or placed at a different path than configured; running in a container without mounting the CA; root-owned file with the service running as non-root; typo in the path.

Understand the failure class

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/b993d20a48dc1f5e. Report an issue: GitHub.