hashicorp/nomad · error

failed to fingerprint internal plugins: %v

Error message

failed to fingerprint internal plugins: %v

What it means

During loader initialization, initInternal instantiates each internal plugin via its factory and fingerprints it. Any error from that step (factory panic-free failure, fingerprint failure) is wrapped with this message and aborts NewPluginLoader.

Source

Thrown at helper/pluginutils/loader/init.go:64

		} else if config.Factory == nil {
			_ = multierror.Append(&mErr, fmt.Errorf("nil factory passed for internal plugin %s", k))
			continue
		}
	}

	return mErr.ErrorOrNil()
}

// init initializes the plugin loader by compiling both internal and external
// plugins and selecting the highest versioned version of any given plugin.
func (l *PluginLoader) init(cfg *PluginLoaderConfig) (map[string]*config.PluginConfig, error) {
	// Create a mapping of name to config
	configMap := configMap(cfg.Configs)

	// Initialize the internal plugins
	internal, err := l.initInternal(cfg.InternalPlugins, configMap)
	if err != nil {
		return nil, fmt.Errorf("failed to fingerprint internal plugins: %v", err)
	}

	// Scan for eligibile binaries
	plugins, err := l.scan()
	if err != nil {
		return nil, fmt.Errorf("failed to scan plugin directory %q: %v", l.pluginDir, err)
	}

	// Fingerprint the passed plugins
	external, err := l.fingerprintPlugins(plugins, configMap)
	if err != nil {
		return nil, fmt.Errorf("failed to fingerprint plugins: %v", err)
	}

	// Merge external and internal plugins
	l.plugins = l.mergePlugins(internal, external)

	// Validate that the configs are valid for the plugins

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the wrapped inner error (%v) to find which internal plugin failed and why.
  2. Verify the plugin's Factory returns an object implementing the full base.BasePlugin interface.
  3. Test the plugin's fingerprint handshake in isolation before loading it via the loader.
  4. Skip registering the problematic internal plugin if it is optional for your build.

Example fix

// before
plugins := map[string]*InternalPluginConfig{"dev": {Factory: myFactory}}

// after
if _, ok := myFactory(ctx, logger).(base.BasePlugin); !ok {
    logger.Warn("plugin does not implement base interface; not registering")
} else {
    plugins["dev"] = &InternalPluginConfig{Factory: myFactory}
}
Defensive patterns

Strategy: try-catch

Validate before calling

for name, ipc := range cfg.InternalPlugins {
    if probe := ipc.Factory(context.Background(), logger); probe == nil {
        return fmt.Errorf("internal plugin %q factory returned nil", name)
    }
}

Type guard

func implementsBasePlugin(raw interface{}) bool {
    _, ok := raw.(base.BasePlugin)
    return ok
}

Try / catch

loader, err := NewPluginLoader(cfg)
if err != nil {
    var inner string = err.Error()
    if strings.Contains(inner, "failed to fingerprint internal plugins") {
        logger.Error("internal plugin init failed", "detail", inner)
        // drop the failing internal plugin and retry
        loader, retryErr := NewPluginLoader(cfgWithoutFailingPlugin)
        ...
    }
    return err
}

Prevention

When it happens

Trigger: An internal plugin's Factory returns an object that fails fingerprinting (BasePlugin handshake fails), or the underlying fingerprint routine errors (unsupported platform, plugin API version mismatch).

Common situations: A custom internal plugin whose implementation doesn't satisfy the fingerprint handshake; architecture/OS where the plugin can't run; version skew between the plugin library and the loader.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/f447591849389e36. Report an issue: GitHub.