Hope this helps improve qlever CLI
Marco
qlever rebuild-index always fails on the default path: CLI copies Qleverfile into the target dir, but the server rejects a non-empty target
Repo: ad-freiburg/qlever-control (CLI). Feature tracked in engine issue #2621.
Summary
qlever rebuild-index, invoked exactly as documented (from the dataset directory,
no extra flags), fails deterministically with:
Rebuilding the index failed: The directory "rebuild.<ts>.tmp" already exists and is not empty
Root cause is a CLI/server contract mismatch. The CLI first creates the new-index
target directory and copies the Qleverfile into it, and only then asks the server
to build the new index into that same directory. The server-side cmd=rebuild-index
refuses to build into a non-empty directory, so the CLI's own cp -a Qleverfile
step guarantees the failure.
This is not macOS-specific and not an engine problem: the engine's
cmd=rebuild-index works and hot-swaps correctly when the target directory is empty
(shown below). The bug is purely in the CLI wrapper's ordering.
Environment
qlever CLI: 0.5.50 (installed via uv tool)
- Image:
adfreiburg/qlever@sha256:6ba10ddf71e7d06ece47eaf927339213c64c342f9ac719ab6c97968d81aef186
(server git hash 634ebb2, compiled 2026-08-03)
SYSTEM = docker; Docker 29.5.2; host macOS 26.6 (mechanism is OS-independent)
Minimal reproduction
data.ttl:
@prefix ex: <http://example.org/> .
ex:a ex:p ex:b .
Qleverfile:
[data]
NAME = ps3
DESCRIPTION = rebuild-index repro
[index]
INPUT_FILES = *.ttl
CAT_INPUT_FILES = cat ${INPUT_FILES}
[server]
PORT = 7035
HOST_NAME = localhost
ACCESS_TOKEN = tok
[runtime]
SYSTEM = docker
IMAGE = docker.io/adfreiburg/qlever:latest
Steps (pristine directory, first-ever rebuild - no leftover rebuild.*/previous.* dirs):
qlever index
qlever start
# make the rebuild non-trivial (optional; fails the same with or without updates):
curl -s localhost:7035 \
--data-urlencode 'update=INSERT DATA { <http://example.org/x> <http://example.org/p> <http://example.org/y> }' \
--data-urlencode 'access-token=tok'
qlever rebuild-index
Observed
Command: rebuild-index
mkdir -p rebuild.<ts>.tmp && cp -a Qleverfile rebuild.<ts>.tmp
curl -s -w '\n%{http_code}' localhost:7035 -d cmd=rebuild-index -d index-name=rebuild.<ts>.tmp/ps3 -d access-token=tok
mkdir -p previous.<ts>.ORIGINAL && mv ps3.* Qleverfile previous.<ts>.ORIGINAL && mv rebuild.<ts>.tmp/* . && rmdir rebuild.<ts>.tmp
Rebuilding the index failed: The directory "rebuild.<ts>.tmp" already exists and is not empty
The rebuild never runs; the server keeps serving the old index (non-destructive).
Isolation (empty vs non-empty target dir)
Talking to the server directly, the only difference is whether the target
directory is empty:
# EMPTY target dir -> success
mkdir dirB
curl -s -w '\nHTTP=%{http_code}\n' localhost:7035 -d cmd=rebuild-index -d index-name=dirB/ps3 -d access-token=tok
# => {"message":"Index successfully rebuilt and swapped in", ...} HTTP=200
# target dir containing only Qleverfile (what the CLI creates) -> failure
mkdir dirA && cp Qleverfile dirA
curl -s -w '\nHTTP=%{http_code}\n' localhost:7035 -d cmd=rebuild-index -d index-name=dirA/ps3 -d access-token=tok
# => The directory "dirA" already exists and is not empty HTTP=400
When it succeeds, the swap is seamless: the server container is not restarted
and continues serving (count preserved across the swap).
Expected
qlever rebuild-index should succeed on the default path.
Suggested fix
Either:
- copy the
Qleverfile into the new-index directory after the server has built
the index there (not before), or
- have the server-side empty-directory check ignore a lone
Qleverfile.
Secondary observations (context, not necessarily separate reports)
- Repeated rebuilds collide on the auto-named
previous.<ts> directory:
The directory "previous.<ts>" already exists and is not empty (HTTP 400) when
rebuilds happen in quick succession / the timestamp basis does not advance.
rebuild-index --new-index-dir <dir>: the validation step starts a throwaway
container (-u $(id -u):$(id -g)) that reports
Could not open ... .meta-data.json ... permissions are insufficient - this one
may be a macOS Docker Desktop uid/bind-mount quirk and needs a Linux cross-check.
- Docs drift: the engine returns
"...rebuilt and swapped in" and does hot-swap
without a restart, but https://docs.qlever.dev/rebuild-index/ still states
"There is currently no way to transition from the old index to the new index
without any interruption."
Hope this helps improve qlever CLI
Marco
qlever rebuild-indexalways fails on the default path: CLI copiesQleverfileinto the target dir, but the server rejects a non-empty targetRepo:
ad-freiburg/qlever-control(CLI). Feature tracked in engine issue #2621.Summary
qlever rebuild-index, invoked exactly as documented (from the dataset directory,no extra flags), fails deterministically with:
Root cause is a CLI/server contract mismatch. The CLI first creates the new-index
target directory and copies the
Qleverfileinto it, and only then asks the serverto build the new index into that same directory. The server-side
cmd=rebuild-indexrefuses to build into a non-empty directory, so the CLI's own
cp -a Qleverfilestep guarantees the failure.
This is not macOS-specific and not an engine problem: the engine's
cmd=rebuild-indexworks and hot-swaps correctly when the target directory is empty(shown below). The bug is purely in the CLI wrapper's ordering.
Environment
qleverCLI: 0.5.50 (installed viauv tool)adfreiburg/qlever@sha256:6ba10ddf71e7d06ece47eaf927339213c64c342f9ac719ab6c97968d81aef186(server git hash
634ebb2, compiled 2026-08-03)SYSTEM = docker; Docker 29.5.2; host macOS 26.6 (mechanism is OS-independent)Minimal reproduction
data.ttl:Qleverfile:Steps (pristine directory, first-ever rebuild - no leftover
rebuild.*/previous.*dirs):Observed
The rebuild never runs; the server keeps serving the old index (non-destructive).
Isolation (empty vs non-empty target dir)
Talking to the server directly, the only difference is whether the target
directory is empty:
When it succeeds, the swap is seamless: the server container is not restarted
and continues serving (count preserved across the swap).
Expected
qlever rebuild-indexshould succeed on the default path.Suggested fix
Either:
Qleverfileinto the new-index directory after the server has builtthe index there (not before), or
Qleverfile.Secondary observations (context, not necessarily separate reports)
previous.<ts>directory:The directory "previous.<ts>" already exists and is not empty(HTTP 400) whenrebuilds happen in quick succession / the timestamp basis does not advance.
rebuild-index --new-index-dir <dir>: the validation step starts a throwawaycontainer (
-u $(id -u):$(id -g)) that reportsCould not open ... .meta-data.json ... permissions are insufficient- this onemay be a macOS Docker Desktop uid/bind-mount quirk and needs a Linux cross-check.
"...rebuilt and swapped in"and does hot-swapwithout a restart, but https://docs.qlever.dev/rebuild-index/ still states
"There is currently no way to transition from the old index to the new index
without any interruption."