Screening Appliance docs

Troubleshooting / FAQ

Stale data, checksum-mismatch resync, health checks for orchestrators, and upgrading to a new image tag.

Last updated 2026-08-02

Troubleshooting / FAQ

My data looks stale β€” how do I tell, and how do I fix it?

Check /v1/status:

curl -s http://localhost:8400/v1/status
  • Compare dataVersion and lastSyncAt against how recent you expect the data to be.
  • nextSyncAt tells you when the appliance will next check for updates on its own, per SYNC_INTERVAL.
  • If OFFLINE=true, syncing never happens automatically at all β€” see Air-gapped operation to side-load an update.

To force a sync right now instead of waiting:

curl -s -X POST http://localhost:8400/v1/admin/sync

If lastSyncAt doesn't advance after that, check container logs for the sync client's error output β€” a persistently failing sync (network policy blocking egress to UPDATE_URL, DNS, a proxy requirement) will keep retrying on SYNC_INTERVAL without updating lastSyncAt on success.

A sync reported (or I suspect) a checksum mismatch β€” what do I do?

Nothing, in most cases. Checksum verification is designed to be self-healing: when a downloaded delta file's checksum doesn't match the manifest, or the applied result's entity count/content checksum doesn't match, the appliance automatically discards the incremental result and does a clean full re-download of that dataset on its own β€” see Checksum verification and self-healing. The previously-verified data keeps serving /v1/search throughout, so there is no window of degraded correctness while this happens.

If you want to force that same clean-re-download path proactively β€” for example, after restoring the volume from a backup, or if you simply want to rule out any accumulated drift β€” trigger it directly:

curl -s -X POST http://localhost:8400/v1/admin/resync

/v1/admin/resync bypasses incremental deltas entirely and re-downloads a full snapshot for every currently-loaded dataset.

What should my orchestrator use for health checks?

GET /healthz β€” designed specifically for liveness/readiness probes:

curl -s http://localhost:8400/healthz
  • ok: true β€” the appliance has a fully-loaded, checksum-verified dataset and is ready to serve /v1/search and /v1/batch. Treat this as "ready."
  • ok: false (or the endpoint not yet responding) β€” the appliance is still loading its initial snapshot (e.g. right after first start) or has failed to reach a servable state. Treat this as "not ready" rather than "unhealthy β€” restart," since a container that has just started still needs time to load the baked-in snapshot from the image layer onto the volume before it can answer ok: true.

For a Docker Compose / Dockerfile HEALTHCHECK:

HEALTHCHECK --interval=30s --timeout=5s --start-period=60s \
  CMD curl -sf http://localhost:8400/healthz | grep -q '"ok":true' || exit 1

--start-period=60s (or longer, depending on your storage backend) gives the appliance time to finish loading its baked-in snapshot on first boot before health checks start counting against it.

How do I upgrade to a new image tag?

Pull the new tag and recreate the container against the same persistent volume β€” the data on the volume, and the sync state that describes it, carry forward untouched:

docker pull proofaml/screening-appliance:2026-08-02

docker stop proofaml-screening
docker rm proofaml-screening

docker run -d \
  --name proofaml-screening \
  -p 8400:8400 \
  -v proofaml-data:/var/lib/proofaml \
  -e DATASETS=all \
  proofaml/screening-appliance:2026-08-02

After the new container starts, confirm it came up against the existing data (rather than re-seeding from whatever baked-in snapshot ships in the new image) by checking /v1/status's dataVersion matches what you had before the upgrade, then let the next scheduled (or manually triggered) sync bring it current.

If the new image ships a new epoch (see Epoch) β€” used for schema or resolver changes β€” the next sync will perform a full snapshot re-download automatically rather than applying incremental deltas. That's expected: an epoch bump means the new image's code and the previous epoch's data are not meant to be mixed.

Why does /v1/search return an empty matches array?

That's a valid, complete answer β€” no candidate cleared the threshold you supplied (or the appliance's default). It is not an error and not distinguishable from "no such entity exists" versus "a match existed but scored below threshold" β€” if you need to see lower-confidence candidates, lower threshold on that request. See POST /v1/search.

Why doesn't /v1/status list a dataset I expected?

/v1/status's datasets array only includes datasets your DATASETS environment variable actually loaded. If you restricted DATASETS to a specific list (rather than all), a dataset outside that list simply won't appear β€” this is expected, not an error. See Dataset selection & reference.

See also


More Screening Appliance docs

← All Screening Appliance docs