grpc/grpc-go · error

provider(%q, %q).Build(%v) failed

Error message

provider(%q, %q).Build(%v) failed

What it means

BuildableConfig.Build() invokes the provider's starter function to create a Provider instance; if the starter returns nil, Build returns this error. The starter is set by the plugin's ParseConfig; for the bundled pemfile plugin newProvider never returns nil, so this is effectively a plugin-author bug or a third-party provider whose factory deliberately returned nil (e.g. internal preconditions not met).

Source

Thrown at credentials/tls/certprovider/store.go:160

// invocations of this method with the same opts will result in provider
// instances being reused.
func (bc *BuildableConfig) Build(opts BuildOptions) (Provider, error) {
	provStore.mu.Lock()
	defer provStore.mu.Unlock()

	sk := storeKey{
		name:   bc.name,
		config: string(bc.config),
		opts:   opts,
	}
	if wp, ok := provStore.providers[sk]; ok {
		wp.refCount++
		return newSingleCloseWrappedProvider(wp), nil
	}

	provider := bc.starter(opts)
	if provider == nil {
		return nil, fmt.Errorf("provider(%q, %q).Build(%v) failed", sk.name, sk.config, opts)
	}
	wp := &wrappedProvider{
		Provider: provider,
		refCount: 1,
		storeKey: sk,
		store:    provStore,
	}
	provStore.providers[sk] = wp
	return newSingleCloseWrappedProvider(wp), nil
}

// String returns the provider name and config as a colon separated string.
func (bc *BuildableConfig) String() string {
	return fmt.Sprintf("%s:%s", bc.name, string(bc.config))
}

// ParseConfig is a convenience function to create a BuildableConfig given a
// provider name and configuration. Returns an error if there is no registered

View on GitHub (pinned to 03255a9237)

Solutions

  1. If you are the plugin author: audit the starter function for any path that returns nil and return a real error instead so the failure is diagnosable.
  2. If you are a user: upgrade or patch the offending provider plugin; verify BuildOptions (CertName, WantRoot, WantIdentity) match what the provider supports.
  3. Switch to the bundled file_watcher or another supported provider name for which Build is guaranteed non-nil.

Example fix

// before (custom plugin)
starter := func(o certprovider.BuildOptions) certprovider.Provider {
    if !o.WantIdentity { return nil } // -> Build() failed
    return newProv(o)
}

// after
starter := func(o certprovider.BuildOptions) certprovider.Provider {
    return newProv(o) // never return nil; surface errors at Build via a wrapping provider
Defensive patterns

Strategy: try-catch

Try / catch

p, err := bc.Build(opts)
if err != nil {
    return fmt.Errorf("provider %s build failed (starter returned nil): %w", bc.String(), err)
}

Prevention

When it happens

Trigger: A custom registered certprovider plugin whose starter closure returns nil for certain BuildOptions; a forked provider whose newProvider has an unhandled early-return path.

Common situations: Writing a custom certificate provider plugin and forgetting to return the constructed provider; an Options combo that the provider does not support leading to a nil return.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/edb055eb5a5134a2. Report an issue: GitHub.