Skip to content

search-indexer image (uid 1000) silently fails to write PROVENANCE_FILE to a root-owned dir, disabling skip-unchanged #661

Description

@ddeboer

Summary

The @lde/search-indexer image runs as the non-root node user (uid 1000), but writes PROVENANCE_FILE without ensuring the target directory is writable by that user. With a root-owned mount (the default for a fresh named volume or a bind-mounted host dir), the provenance file is silently never written, so skip-unchanged never engages and every run reprocesses the full dataset.

Symptom

Configured per the docs with a persisted provenance location:

volumes:
  - provenance:/provenance
environment:
  PROVENANCE_FILE: /provenance/provenance.json

The run completes successfully (exit 0) and indexes correctly, but a second, identical run does not skip – it re-imports and re-projects everything. Inspecting the volume afterwards:

$ docker run --rm -v search-indexer_provenance:/p alpine ls -la /p
drwxr-xr-x root root  .        # <- root-owned, mode 755
                                # (no provenance.json)

The directory is empty: node (uid 1000) cannot create provenance.json in a root:root 755 dir, and the failure is not surfaced.

Expected

Either:

  • the pipeline/image ensures the PROVENANCE_FILE parent directory is writable by the runtime user (e.g. chown/mkdir in the entrypoint, the way DATA_DIR is handled), or
  • a failed provenance write is reported as an error rather than swallowed, so a misconfigured mount is caught instead of silently disabling skip-unchanged.

At minimum, document that PROVENANCE_FILE’s directory must be writable by uid 1000.

Impact

Skip-unchanged is a headline feature for cron-driven reindexing (avoid rebuilding QLever + re-projecting an unchanged dump every tick). As shipped it is silently inert on the most natural configuration. Indexing correctness is unaffected – re-runs are idempotent and produce identical counts – but the optimization never kicks in.

Notes

Runtime user confirmed:

$ docker run --rm --entrypoint sh ghcr.io/ldelements/search-indexer:latest -c 'id'
uid=1000(node) gid=1000(node) groups=1000(node)

Related: #652 (the indexer image), #634 (the file-backed ProvenanceStore this consumes).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions