Troubleshooting
A short list of things that go wrong and how to fix them. If none of these match, check the request id in the response envelope and grep the ScaiGrid logs.
Widget never appears#
- Open your browser's developer console. The widget logs an obvious error if it can't initialise.
- Check the script
srcattribute is actually loading — usually a CSPscript-srcissue. - Check
data-bot-idis a real bot id (not the slug). - Check
data-tokenis a fresh embed token ordata-token-urlpoints at a working endpoint.
Widget loads, "Connection error" on first message#
The chat POST is being blocked or 4xx-ing.
- 403 — token expired or revoked. Check token TTL; mint a new one.
- 404 — wrong bot id or the bot's status is
archived. - 502 / 504 — ScaiGrid is upstream-unhealthy; check
/health/ready. - CSP error in console —
connect-srcmust allowhttps://scaigrid.scailabs.ai.
Bot replies with "I don't have that information"#
Knowledge retrieval returned nothing relevant. Causes:
- Documents haven't indexed yet. Check
GET /bots/{id}/documents— all should showstatus: indexed. - Knowledge disabled.
knowledge_enabledis false on the bot. - Wrong collection. In linked mode,
knowledge_collection_idpoints at a collection the bot's tenant doesn't have access to. - Score threshold too high. Drop
knowledge_settings.score_threshold(default 0.3 — try 0.2 if your corpus is small). - Query mismatch. Visitor's wording doesn't match the document's vocabulary; teach the bot synonyms via
terminologyon the tone.
Bot confabulates#
Says confident things that aren't in the docs.
- Make sure
knowledge_enabledis on. (Sounds silly — easy to forget on a re-created bot.) - Tighten
knowledge_settings.score_threshold(raise it: 0.4–0.5). - Add a
custom_instructionsline: "Answer only from the provided context. If the context doesn't contain the answer, say you don't know." - Add a
confidence-trigger escalation as a safety net.
Citations point at the wrong document#
Two near-duplicate documents in the index — typical with multiple versions of the same PDF.
- Delete the duplicate(s).
- Set
max_chunks_per_doc: 1to force diversity. - Set
deduplicate: true(default true; double-check).
Escalation rule never fires#
In priority order:
- Keyword: check
match_mode(substring vs regex). Substring is case-sensitive; regex needs to be valid Python regex. - Intent: raise the
thresholdif the classifier is too cautious, or lower if too aggressive. Try the live preview atPOST /bots/{id}/escalations/previewto see what the classifier scores against your visitor messages. - Sentiment: the threshold is on a
-1to+1scale;-0.6means "noticeably negative." For "annoyed but polite" set-0.3. - Confidence: the bot's self-reported confidence is heuristic. Combine with
consecutive_low_turns: 2to avoid one-off misfires. - Explicit: language-specific. If your visitors write in a language other than the bot's
language, setstrict_language: falseso detection still works.
Escalation rule fires too often#
Usually the keyword list is too broad ("help" is a terrible escalation trigger) or the sentiment threshold is too lax.
- Reduce keyword list to terms unambiguous to your domain ("refund" yes, "money" no).
- Raise sentiment threshold (closer to zero = stricter — fewer trigger).
- Move the rule down the priority list so cheaper / more specific rules match first.
Document upload returns 500 / fails to index#
- Check the file isn't password-protected (encrypted PDFs are rejected).
- Check the document has selectable text. Scanned PDFs are OCR'd but quality varies; if OCR fails, the document is marked
failed. - Try a smaller document — if a 30 MB PDF fails, the timeout may be the culprit. Split and re-upload.
- Check the document content — corrupted PDFs from old scanners are surprisingly common.
Tokens spent per conversation feels high#
- Check
max_context_messages— default 20 is a lot of history. Drop to 10 if your conversations are usually short. - Check
max_tokens_per_response— 500 is generous. Drop to 300 if responses don't need to be long. - Check
knowledge_settings.top_k— each retrieved chunk costs tokens. Drop from 5 to 3 if your chunks are large. - Verbose tone burns tokens.
verbosity: "concise"is the default for a reason.
Conversations not attributing to logged-in users#
- The widget's
data-user-*attributes are advisory. Mint embed tokens server-side withvisitor_idbaked in. - Check the token's payload (decode it client-side in dev tools) — the visitor id should be there.
- The widget caches its conversation id per visitor. If a logged-in user clears cookies, they'll start a new conversation under a new visitor id; expected behaviour.
Webhook action fires but downstream never receives#
- ScaiGrid retries 3 times with exponential backoff. After that, the escalation event is marked
delivery_failedin the conversation log. - Check your endpoint accepts POSTs with
Content-Type: application/jsonand HMAC headers. - Test signature verification with a fixed timestamp + body — sometimes the body bytes differ between what ScaiGrid signs and what your framework receives (Content-Length differences from middleware).
Conversations dropping after a few minutes of idleness#
By design — conversations time out after 30 minutes of inactivity and the visitor sees the welcome message on their next interaction. Override per-bot with conversation_idle_timeout_seconds.