questdb/questdb · critical · BootstrapException

Could not extract log configuration file

Error message

Could not extract log configuration file

What it means

Thrown when copyLogConfResource() raises an IOException while extracting the bundled log configuration resource into the root directory. Before the logger starts, Bootstrap copies the default log.conf into <root>/conf/log.conf; any I/O failure during that copy (unwritable dir, disk full, missing classpath resource) surfaces as this generic message.

Source

Thrown at core/src/main/java/io/questdb/Bootstrap.java:130

        rootDirectory = argsMap.get("-d");
        if (Chars.isBlank(rootDirectory)) {
            throw new BootstrapException("Root directory name expected (-d <root-path>)");
        }
        final File rootPath = new File(rootDirectory);
        if (!rootPath.exists()) {
            throw new BootstrapException("Root directory does not exist: " + rootDirectory);
        }

        if (argsMap.get("-n") == null && Os.type != Os.WINDOWS) {
            Signal.handle(new Signal("HUP"), _ -> { /* suppress HUP signal */ });
        }

        // before we set up the logger, we need to copy the conf file
        byte[] buffer = new byte[1024 * 1024];
        try {
            copyLogConfResource(buffer);
        } catch (IOException e) {
            throw new BootstrapException("Could not extract log configuration file");
        }

        // setup logger
        // note: this call must be made before any Log init.
        if (argsMap.get(SWITCH_USE_DEFAULT_LOG_FACTORY_CONFIGURATION) == null) {
            LogFactory.configureRootDir(rootDirectory);
        }
        log = LogFactory.getLog(LOG_NAME);

        try {
            copyResource(rootDirectory, false, buffer, "import/readme.txt", log);
            copyResource(rootDirectory, false, buffer, "import/trades.parquet", log);
        } catch (IOException e) {
            throw new BootstrapException("Could not create the default import directory");
        }

        // report copyright and architecture
        log.advisoryW()

View on GitHub (pinned to 6610ab113b)

Solutions

  1. Ensure the user running QuestDB has write permission on the root dir: chown -R questdb: /var/lib/questdb or chmod u+w
  2. Check disk space (df -h <root>) and free space if full
  3. If using a custom/shaded build, verify the log conf resource is packaged on the classpath, or pass the switch that skips copying and use LogFactory's default configuration

Example fix

# before: root owned by root, server runs as questdb
ls -ld /var/lib/questdb  # drwxr-xr-x root root

# after
chown -R questdb:questdb /var/lib/questdb
Defensive patterns

Strategy: validation

Validate before calling

File confDir = new File(rootDir, "conf");
if (!confDir.exists() && !confDir.mkdirs()) {
    throw new IllegalStateException("Cannot create or write " + confDir + " - check permissions/disk");
}
new Bootstrap(Bootstrap.getServerMainArgs(rootDir));

Try / catch

try {
    bootstrap = new Bootstrap(args);
} catch (Bootstrap.BootstrapException e) {
    // I/O environment problem: fix filesystem (perms/space), restart the JVM
}

Prevention

When it happens

Trigger: Root directory exists but the <root>/conf subdirectory cannot be created or written (read-only filesystem, no write permission, SELinux denial); disk full; or a repackaged/shaded jar where the log conf resource is missing from the classpath.

Common situations: Running QuestDB against a root dir owned by another user; Docker read-only volume mounts; minimal/shaded jars built without resources; disk exhaustion.

Related errors


AI-assisted analysis of questdb/questdb@6610ab113b (2026-08-14). Data as JSON: /api/errors/76b06d85e7434646. Report an issue: GitHub.