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
- 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
- If you intended the default, remove the property so it falls back to tmpRoot
- 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
- Give COPY work a dedicated directory on a fast local disk outside the install tree
- Remember the check uses canonical paths, so symlinks to protected dirs are also rejected
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
- Server configuration file does not exist! ${configFile}
- Invalid log locale: '${logTimestampLocaleStr}'
- Invalid log timezone: '${logTimestampTimezone}'
- Configuration value for ${PropertyKey.CAIRO_AUTO_SCALE_SYMBO
- ${PropertyKey.CAIRO_CHECKPOINT_RECOVERY_THREADPOOL_MIN.prope
AI-assisted analysis of questdb/questdb@6610ab113b (2026-08-14).
Data as JSON: /api/errors/cd460812955e9839.
Report an issue: GitHub.