Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Modellen Tools & Services
Oplossingen
Organisaties Ontwikkelaars Internet Service Providers Managed Service Providers AI-in-a-Box
Kenniscentrum
Ondersteuning Documentation Blog Downloads
Bedrijf
Over ons Onderzoek Vacatures Investeren Contact
Inloggen

Troubleshooting

This page maps common symptoms to their cause and fix. Each subsection is one symptom you can recognize from a log line, an exception, or a counter. Every behaviour here is a deliberate design choice — ScaiLog fails safe (never leaking PI, never silently dropping) rather than failing convenient, so most of these are signals telling you what to fix.

Logs appear on stderr as JSON instead of reaching the server#

Symptom. Your service prints ScaiLog entries as newline-delimited JSON to stderr (landing in container or journald logs), and PI field values show up as {"type": "...", "redacted": true} instead of their real value.

Cause. The SDK could not reach the local agent socket, or its in-process queue was full. Rather than drop the entry silently, the SDK falls back to stderr in the same NDJSON shape — and it redacts PI values first, keeping the field name and PI type so the drop is auditable but no plaintext leaks into stderr.

Fix. Make sure the agent (or a standalone server's embedded agent) is running and that SCAILOG_SOCKET points at the socket it is listening on (default /run/scailog/agent.sock). Confirm file permissions let your service connect. Once the socket is reachable, entries flow over it again. A rising dropped_to_stderr count is your signal that the agent is unavailable or your emit rate is exceeding the queue.

SUBJECT_REQUIRED#

Symptom. An emit call raises ValueError: SUBJECT_REQUIRED: entry has PI markers but no subject= (Python), the entry is rejected with a SUBJECT_REQUIRED diagnostic (TS/Go/.NET), or an ingested batch entry is nacked with SUBJECT_REQUIRED.

Cause. The entry carries one or more pi() fields but no subject. Any PI requires a data subject to attach it to — that's what makes cryptographic erasure possible. The rule is enforced in the SDK before the entry leaves the process, and again at the agent and server.

Fix. Pass the data-subject id on the emit call (subject=...), or set it on the ambient context (e.g. withContext/WithSubject/LogContext.Push) so it propagates automatically. If the field isn't actually about a natural person, don't mark it pi().

invalid call_site_id#

Symptom. An emit call raises ValueError: invalid call_site_id: '...' (pattern ^[A-Z0-9]+(-[A-Z0-9]+){2,}$), or scailog-ci check fails the build on a call site.

Cause. Every entry needs a developer-assigned call_site_id, and it must match ^[A-Z0-9]+(-[A-Z0-9]+){2,}$ — at least three uppercase-alphanumeric segments joined by hyphens, e.g. SCAI-CHECKOUT-PAID-001. Call-site provenance is first-class in ScaiLog (GDPR remediation is "fix one call site"), so the id can't be blank, lowercase, or too few segments. The AUTO- and SCAILOG- prefixes are reserved for the system.

Fix. Give the call site a constant, unique, well-formed id. Run scailog-ci check in CI to catch bad or interpolated ids before they ship — it also enforces that the id is a constant (not built from a variable) and that pi() is accompanied by a subject.

Entries turn into [PANIC_DROPPED:...] (SCAILOG-AGENT-PANIC-DROP-001)#

Symptom. A PI field is stored as [PANIC_DROPPED:<pi_type>] in the entry metadata, the agent's panic_drops counter rises, and the agent emits a warning under call site SCAILOG-AGENT-PANIC-DROP-001: "refused to cache plaintext PI: server unreachable and no DEK available".

Cause. The agent needs a per-subject DEK to encrypt PI, and it couldn't get one — the server was unreachable (so enrollment or DEK fetch failed), or the subject was erased (the server returns HTTP 410, the key is gone). Rather than write plaintext PI to its local cache, the agent enters panic mode and drops the value, loudly.

Fix. Restore connectivity to the server and confirm the agent's API key is valid, then new entries encrypt and ship normally. If the drops are for an erased subject, that is correct behaviour — the key was destroyed by design and cannot come back. Never reach for --fail-open in production to make the drops stop: it caches plaintext PI and exists only for dev.

A console script prints pip install 'scailog[...]' and exits#

Symptom. Running scailog, scailog-server, scailog-agent, or scailog-audit exits immediately with, e.g.:

text
1
2
3
scailog-server needs the 'server' extra, which isn't installed.
    pip install 'scailog[server]'
(missing dependency: fastapi)

Cause. The base install is the pure-stdlib SDK, which carries none of the server/agent/CLI/audit dependencies. The console scripts are wrapped so a missing extra becomes a one-line install hint instead of a raw ModuleNotFoundError traceback.

Fix. Install the extra named in the hint, e.g. pip install 'scailog[server]' (or agent, cli, audit, or all). Note scailog-ci is the exception — it is zero-dependency and runs on the base install. (If the missing dependency is a scailog.* submodule rather than a third-party package, that's a genuine bug and is re-raised untouched — it won't be masked by an install hint.)

RESERVED_FIELD rejection#

Symptom. An emit call raises ValueError: reserved field name: '...' (Python) or the entry is rejected/nacked with RESERVED_FIELD.

Cause. A field name collides with a reserved top-level entry key. These names are reserved: event_id, tenant, service, env, site, level, ts, msg, fields, pi, subject, trace_id, request_id. Allowing them as user fields would let a field shadow a protocol key.

Fix. Rename the field to something outside that set (e.g. use user_service instead of service). The check runs on both plain fields and pi() fields.

PI never gets encrypted — it's kept or dropped instead#

Symptom. A field you marked pi() shows up in plaintext fields (or is gone) rather than encrypted, and the entry metadata records an action of keep, redact, or drop.

Cause. The policy engine decides the action per PI type. Not every type defaults to encrypt: pseudonymous defaults to keep, and credentials and special_category default to drop (credentials and special-category data are dropped, not stored encrypted). Your policy may also override the default for a service or environment.

Fix. Check the effective policy for the service/env/PI-type combination (scailog explain / the policies view). If a type should be encrypted, set an encrypt action for it in your policy. If you marked the wrong PI type, fix the marker at the call site.

Updated 2026-07-13 09:41:42 View source (.md) rev 2