questdb/questdb · error · ServerConfigurationException

Configuration value for ${PropertyKey.CAIRO_SQL_COPY_WORK_RO

Error message

Configuration value for ${PropertyKey.CAIRO_SQL_COPY_WORK_ROOT.propertyPath} can't point to root, data, conf or snapshot dirs.

What it means

Thrown by PropServerConfiguration when cairo.sql.copy.work.root canonicalizes to the same path as the install root, db root, conf root, or checkpoint/snapshot root. QuestDB uses this directory as scratch space for COPY operations and rejects configurations that would make COPY work files collide with database or config directories.

Source

Thrown at core/src/main/java/io/questdb/PropServerConfiguration.java:1028

        String configuredCairoSqlCopyRoot = getString(properties, env, PropertyKey.CAIRO_SQL_COPY_ROOT, "import");
        if (!Chars.empty(configuredCairoSqlCopyRoot)) {
            if (new File(configuredCairoSqlCopyRoot).isAbsolute()) {
                this.cairoSqlCopyRoot = configuredCairoSqlCopyRoot;
            } else {
                if (absDbDir) {
                    this.cairoSqlCopyRoot = rootSubdir(this.dbRoot, configuredCairoSqlCopyRoot); // ../import
                } else {
                    this.cairoSqlCopyRoot = new File(installRoot, configuredCairoSqlCopyRoot).getAbsolutePath();
                }
            }
            String cairoSqlCopyWorkRoot = getString(properties, env, PropertyKey.CAIRO_SQL_COPY_WORK_ROOT, tmpRoot);
            this.cairoSqlCopyWorkRoot = getCanonicalPath(cairoSqlCopyWorkRoot);
            if (pathEquals(installRoot, this.cairoSqlCopyWorkRoot)
                    || pathEquals(this.dbRoot, this.cairoSqlCopyWorkRoot)
                    || pathEquals(this.confRoot, this.cairoSqlCopyWorkRoot)
                    || pathEquals(this.checkpointRoot, this.cairoSqlCopyWorkRoot)) {
                throw new ServerConfigurationException(
                        "Configuration value for "
                                + PropertyKey.CAIRO_SQL_COPY_WORK_ROOT.getPropertyPath()
                                + " can't point to root, data, conf or snapshot dirs."
                );
            }
        } else {
            this.cairoSqlCopyRoot = null;
            this.cairoSqlCopyWorkRoot = null;
        }

        String configuredCairoSqlCopyExportRoot = getString(properties, env, PropertyKey.CAIRO_SQL_COPY_EXPORT_ROOT, "export");
        if (!Chars.empty(configuredCairoSqlCopyExportRoot)) {
            if (new File(configuredCairoSqlCopyExportRoot).isAbsolute()) {
                this.cairoSqlCopyExportRoot = configuredCairoSqlCopyExportRoot;
            } else {
                if (absDbDir) {
                    this.cairoSqlCopyExportRoot = rootSubdir(this.dbRoot, configuredCairoSqlCopyExportRoot); // ../export
                } else {

View on GitHub (pinned to 6610ab113b)

Solutions

  1. Point cairo.sql.copy.work.root at a dedicated scratch directory outside the install/db/conf/snapshot trees, e.g. /var/lib/questdb/copy-work or the default tmp root
  2. If you intended the default, remove the property so it falls back to tmpRoot
  3. Check for symlinks: the comparison uses canonical paths, so a link to the db root is also rejected

Example fix

# before
cairo.sql.copy.work.root=/var/lib/questdb/db

# after
cairo.sql.copy.work.root=/var/lib/questdb/copy-work
Defensive patterns

Strategy: validation

Validate before calling

Path work = Paths.get(props.getProperty("cairo.sql.copy.work.root", tmpRoot)).toRealPath();
List<Path> forbidden = List.of(installRoot, dbRoot, confRoot, checkpointRoot).stream()
        .map(p -> { try { return p.toRealPath(); } catch (IOException e) { return p; } })
        .toList();
if (forbidden.contains(work)) {
    throw new IllegalArgumentException("cairo.sql.copy.work.root collides with a protected dir: " + work);
}

Try / catch

try {
    new PropServerConfiguration(...);
} catch (ServerConfigurationException e) {
    // point the property at a dedicated scratch dir and restart
}

Prevention

When it happens

Trigger: Setting cairo.sql.copy.work.root='.', '' resolving to the install root, the db directory, conf directory, or the snapshot dir in server.conf; also symlinks that canonicalize onto one of those roots (pathEquals compares canonical paths).

Common situations: Trying to keep copy work files 'tidy' by pointing them at the server root; env-var overrides in orchestration that accidentally set it to the data dir; migrating configs between versions where defaults changed.

Related errors


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