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 level

View on GitHub (pinned to 820761864e)

Solutions

  1. Ensure only one process/instance opens the data directory; kill the other holder or change the rocksdb:// path.
  2. Check RocksDB LOG and the wrapped cause for LOCK held / Corruption / IO errors.
  3. Remove stale LOCK only after confirming no process is using the directory, or restore from backup if corruption is reported.
  4. 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

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/a58010ddee11d2f8. Report an issue: GitHub.