apache/pulsar · error · RuntimeException
is not an instance of MetadataStore
Error message
is not an instance of MetadataStore
What it means
BookieRackAffinityMapping.getMetadataStore reads the METADATA_STORE_INSTANCE property from the BookKeeper configuration. If that property is set but holds an object that is not a MetadataStore (wrong type injected programmatically), a RuntimeException naming the property is thrown.
Source
Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/bookie/rackawareness/BookieRackAffinityMapping.java:78
public class BookieRackAffinityMapping extends AbstractDNSToSwitchMapping
implements RackChangeNotifier {
public static final String BOOKIE_INFO_ROOT_PATH = "/bookies";
public static final String METADATA_STORE_INSTANCE = "METADATA_STORE_INSTANCE";
private MetadataCache<BookiesRackConfiguration> bookieMappingCache = null;
private volatile ITopologyAwareEnsemblePlacementPolicy<BookieNode> rackawarePolicy = null;
private List<BookieId> bookieAddressListLastTime = new ArrayList<>();
private BookiesRackConfiguration racksWithHost = new BookiesRackConfiguration();
private Map<String, BookieInfo> bookieInfoMap = new HashMap<>();
static MetadataStore getMetadataStore(Configuration conf) throws MetadataException {
MetadataStore store;
Object storeProperty = conf.getProperty(METADATA_STORE_INSTANCE);
if (storeProperty != null) {
if (!(storeProperty instanceof MetadataStore)) {
throw new RuntimeException(METADATA_STORE_INSTANCE + " is not an instance of MetadataStore");
}
store = (MetadataStore) storeProperty;
} else {
String url;
String metadataServiceUri = ConfigurationStringUtil.castToString(conf.getProperty("metadataServiceUri"));
if (StringUtils.isNotBlank(metadataServiceUri)) {
try {
url = metadataServiceUri.replaceFirst(METADATA_STORE_SCHEME + ":", "")
.replace(";", ",");
} catch (Exception e) {
throw new MetadataException(Code.METADATA_SERVICE_ERROR, e);
}
} else {
String zkServers = ConfigurationStringUtil.castToString(conf.getProperty("zkServers"));
if (StringUtils.isBlank(zkServers)) {
String errorMsg = String.format("Neither %s configuration set in the BK client configuration nor "
+ "metadataServiceUri/zkServers set in bk server configuration", METADATA_STORE_INSTANCE);
throw new RuntimeException(errorMsg);View on GitHub (pinned to 820761864e)
Solutions
- Set METADATA_STORE_INSTANCE to an actual org.apache.pulsar.metadata.api.MetadataStore instance
- Or remove the property and supply metadataServiceUri / zkServers so the store is created from a URI
- Check the injected object is not a mock/wrapper — use MetadataStoreExtended.create() to build it
Example fix
// before
conf.setProperty(METADATA_STORE_INSTANCE, mockStoreBuilder); // wrong type
// after
MetadataStore store = MetadataStoreExtended.create("zk+sasl://zk1:2181/ledgers", ...);
conf.setProperty(METADATA_STORE_INSTANCE, store); Defensive patterns
Strategy: type-guard
Validate before calling
Object v = conf.getProperty(METADATA_STORE_INSTANCE);
if (v != null && !(v instanceof MetadataStore)) {
throw new IllegalArgumentException("METADATA_STORE_INSTANCE must be a MetadataStore");
} Type guard
static boolean isValidStore(Object o) {
return o == null || o instanceof MetadataStore;
} Try / catch
try {
mapping.setConf(conf);
} catch (RuntimeException e) {
log.error("bad METADATA_STORE_INSTANCE", e);
} Prevention
- Only inject real MetadataStore instances programmatically
- Prefer URI-based config (metadataServiceUri) over object injection
- Update mocks/tests after MetadataStore API changes
When it happens
Trigger: A Configuration passed to setConf()/initialize() contains METADATA_STORE_INSTANCE bound to an object of a type other than MetadataStore — only possible via programmatic configuration, not string config files.
Common situations: Embedding BookKeeper/Pulsar in tests or custom code and passing a mock, a different store implementation, or a Supplier/wrapper object under that key; type changes across library versions.
Related errors
- Metadata store address argument is required (--metadata-stor
- Neither METADATA_STORE_INSTANCE configuration set in the BK
- Failed to load config into existing configuration data
- does not implement
- Function runtime customizer %s must implement KubernetesMani
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/f0611bf6edc8cb65.
Report an issue: GitHub.