apache/pulsar · critical · MetadataStoreException
Error open RocksDB database
Error message
Error open RocksDB database
What it means
openDB() configures Options/TransactionDBOptions and calls TransactionDB.open on the data path. Any RocksDBException from the native open (lock, IO, options, corruption) is wrapped as MetadataStoreException('Error open RocksDB database'). Other Throwables are wrapped generically.
Source
Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/impl/RocksdbMetadataStore.java:309
List<ColumnFamilyHandle> cfHandles = new ArrayList<>();
try {
return TransactionDB.open(dbOptions, transactionDBOptions, dataPath, cfDescriptors, cfHandles);
} finally {
dbOptions.close();
configOptions.close();
}
} else {
Options options = new Options();
options.setCreateIfMissing(true);
configLog(options);
try {
return TransactionDB.open(options, transactionDBOptions, dataPath);
} finally {
options.close();
}
}
} catch (RocksDBException e) {
throw new MetadataStoreException("Error open RocksDB database", e);
} catch (Throwable t) {
throw MetadataStoreException.wrap(t);
}
}
private void configLog(Options options) throws IOException {
// Configure file path
String logPath = System.getProperty("pulsar.log.dir", "");
Path logPathSetting;
if (!logPath.isEmpty()) {
logPathSetting = FileSystems.getDefault().getPath(logPath + "/rocksdb-log");
Files.createDirectories(logPathSetting);
options.setDbLogDir(logPathSetting.toString());
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");
Files.setPosixFilePermissions(logPathSetting, perms);
}
// Configure log levelView on GitHub (pinned to 820761864e)
Solutions
- Ensure only one process/instance opens the data directory; kill the other holder or change the rocksdb:// path.
- Check RocksDB LOG and the wrapped cause for LOCK held / Corruption / IO errors.
- Remove stale LOCK only after confirming no process is using the directory, or restore from backup if corruption is reported.
- Fix file ownership/permissions on the existing DB directory for the running user.
Defensive patterns
Strategy: retry
Validate before calling
Path dir = Path.of(rocksdbUrl.substring("rocksdb:".length()));
try (var lockCheck = Files.list(dir)) {
if (Files.exists(dir.resolve("LOCK"))) {
// another process may hold the DB — verify before opening
}
}
if (!Files.isWritable(dir)) throw new IllegalStateException("DB dir not writable: " + dir); Try / catch
try {
MetadataStore s = MetadataStoreFactory.create(rocksdbUrl);
} catch (MetadataStoreException e) {
if (e.getMessage().contains("Error open RocksDB database")) {
// check LOCK holder, permissions, corruption per wrapped RocksDBException
} else throw e;
} Prevention
- Guarantee a single process per data directory (container orchestration anti-affinity)
- Configure separate rocksdb:// paths per instance in tests running in parallel
- Monitor RocksDB LOG for early corruption/IO warnings
When it happens
Trigger: Starting a second RocksdbMetadataStore instance against the same rocksdb:// directory (LOCK file held), the directory containing a corrupt SST/WAL file, invalid options, or unwritable/missing files.
Common situations: Two Pulsar processes pointed at the same data directory; a crashed process left a stale lock (rare — lock persists while process lives); corrupted DB after crash/restore; running as a user without write access to existing DB files.
Related errors
- Unable to delete ${file}
- Invalid MetaValue data, size=${size}
- Invalid MetaValue data, no enough header data. expect %d, ac
- Invalid MetaValue format version=${version}
- Failed to load RocksDB JNI library
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/a58010ddee11d2f8.
Report an issue: GitHub.