{"record":{"id":"375ae575c3029823","repo":"apache/pulsar","slug":"metadata-cache-implementation-classname-not-sup","errorCode":null,"errorMessage":"Metadata cache implementation ${className} not supported by FaultInjectionMetadataStore","messagePattern":"Metadata cache implementation (.+?) not supported by FaultInjectionMetadataStore","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"pulsar-metadata/src/main/java/org/apache/pulsar/metadata/impl/FaultInjectionMetadataStore.java","lineNumber":193,"sourceCode":"\n    @Override\n    public <T> MetadataCache<T> getMetadataCache(TypeReference<T> typeRef, MetadataCacheConfig<?> cacheConfig) {\n        return injectMetadataStoreInMetadataCache(store.getMetadataCache(typeRef, cacheConfig));\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Override\n    public <T> MetadataCache<T> getMetadataCache(String cacheName, MetadataSerde<T> serde,\n                                                 MetadataCacheConfig<?> cacheConfig) {\n        return injectMetadataStoreInMetadataCache(store.getMetadataCache(serde, cacheConfig));\n    }\n\n    @SneakyThrows\n    private <T> MetadataCache<T> injectMetadataStoreInMetadataCache(MetadataCache<T> metadataCache) {\n        if (metadataCache instanceof MetadataCacheImpl) {\n            FieldUtils.writeField(metadataCache, \"store\", this, true);\n        } else {\n            throw new UnsupportedOperationException(\"Metadata cache implementation \"\n                    + metadataCache.getClass().getName() + \" not supported by FaultInjectionMetadataStore\");\n        }\n        return metadataCache;\n    }\n\n    @Override\n    public void registerSessionListener(Consumer<SessionEvent> listener) {\n        store.registerSessionListener(listener);\n        sessionListeners.add(listener);\n    }\n\n    @Override\n    public CompletableFuture<Void> handleMetadataEvent(MetadataEvent event) {\n        return store.handleMetadataEvent(event);\n    }\n\n    @Override\n    public void close() throws Exception {","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/impl/FaultInjectionMetadataStore.java#L175-L211","documentation":"FaultInjectionMetadataStore is a test wrapper that must inject itself into every MetadataCache it hands out, replacing the cache's internal `store` field. It can only do this for MetadataCacheImpl instances; for any other MetadataCache implementation it throws UnsupportedOperationException naming the class, after reflectively overwriting the field via FieldUtils.","triggerScenarios":"Calling FaultInjectionMetadataStore.getMetadataCache() when the underlying store returns a non-MetadataCacheImpl cache implementation — typically a custom or third-party MetadataCache subclass.","commonSituations":"Using FaultInjectionMetadataStore in tests with a custom metadata store/cache implementation that does not extend MetadataCacheImpl.","solutions":["Use a metadata store whose getMetadataCache returns standard MetadataCacheImpl instances (e.g., the built-in ZK/Oxia/RocksDB stores)","Update the custom MetadataCache implementation to extend MetadataCacheImpl","Only wrap stores with FaultInjectionMetadataStore that are known-compatible in tests"],"exampleFix":"// before\nFaultInjectionMetadataStore faultStore = new FaultInjectionMetadataStore(customStore); // custom cache\n// after\nFaultInjectionMetadataStore faultStore = new FaultInjectionMetadataStore(new OxiaMetadataStore(cfg));","handlingStrategy":"type-guard","validationCode":"// Java: only wrap stores whose caches are standard impls\nMetadataCache<?> cache = store.getMetadataCache(String.class);\nif (!(cache instanceof MetadataCacheImpl)) {\n    throw new IllegalStateException(\"Store not compatible with FaultInjectionMetadataStore\");\n}\n","typeGuard":"static boolean supportsFaultInjection(MetadataCache<?> cache) {\n    return cache instanceof MetadataCacheImpl;\n}\n","tryCatchPattern":"try {\n    MetadataCache<T> c = faultStore.getMetadataCache(String.class);\n} catch (UnsupportedOperationException e) {\n    // store returns a non-standard cache; switch to a built-in store in tests\n}\n","preventionTips":["Use built-in metadata stores (zk:, oxia:, rocksdb:, memory:) in fault-injection tests","Keep custom MetadataCache implementations extending MetadataCacheImpl","Check compatibility before wrapping a store with FaultInjectionMetadataStore"],"tags":["test","reflection","metadata-cache","fault-injection"],"backgroundTag":"unsupported-cache-implementation","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}