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 for persona_ log events.
Publishing returns PERSONA_MODEL_NOT_FOUND#
The model_slug on the persona doesn't resolve to a frontend model in the catalogue. Either you mistyped the slug, the underlying model was deleted, or the model exists but isn't visible to your tenant.
- Check
/v1/modelsand verify the exact slug. - If the model was unintentionally deleted, restore or recreate it. The persona row stays valid until you fix this.
Caller gets model not found invoking a published persona#
The published model's slug is tenant/{tenant_slug}/{persona_slug}, not the persona's own slug. Inspect the persona's published_model_id to find the frontend model, then look up its slug.
Common mistakes:
- Using the bare
slug("acme-support") instead of the tenant-qualified slug. - Wrong tenant slug — the tenant's slug, not the tenant id.
- Persona was unpublished while the caller was caching the slug.
Persona answers from system prompt, ignores attached sources#
Retrieval ran but returned nothing useful. Causes:
- RAG disabled. Check
rag_enabledistrueon the persona. - No active sources. Listed sources may have
status: "disabled". List them and re-enable. - Collection access denied. If your collection is ACL'd, the invoking caller may not have read access. The enricher silently drops chunks the caller can't see. Test as a user who has the access.
rag_min_scoretoo high. Drop it (try 0.3 — 0.4) to let weaker matches through.- Wrong collection id. A typo on the source — the enricher logs
persona_rag_collection_search_errorif the collection lookup fails. Verify by listing sources on the persona.
Persona confabulates#
Says confident things that aren't in the source corpus.
- The persona's
system_promptshould explicitly tell the model to answer only from context. The default behaviour is permissive. - Tighten
rag_min_score. With weak chunks gone, the model has fewer false anchors to confabulate from. - Drop
rag_top_kif you're injecting too much marginally-relevant context. - Move from
single_steptomulti_step— the LLM-refined query often surfaces better chunks.
ScaiDrive shares list returns 503 or 502#
- 503
SCAIDRIVE_NOT_CONFIGURED— the module doesn't have ascaidrive_base_urlset in module config. Set it via the modules admin API. - 502
SCAIDRIVE_TOKEN_EXCHANGE_FAILED— the caller's token can't be exchanged. Most common cause: API keys without ScaiDrive scope. Retry with a JWT-authed caller.
ScaiDrive source returns no chunks at invocation time, even though /scaidrive/shares listed the share#
Token exchange succeeded for the listing call but failed at retrieval time, or ScaiDrive itself rejected the search.
- Check logs for
persona_rag_token_exchange_error(exchange failed mid-invocation) orscaidrive_search_error(search call failed). - If the calling identity changed between listing and invocation (e.g. shared API key vs end-user JWT), the access set differs — that's expected.
Publishing assigns to no groups even though group_ids was passed#
Group-scope validation rejected the assignments. The check is silent — group ids outside the caller's scope are dropped.
- A super-admin can target any group.
- A partner-admin can target partner-scoped groups for their partner only.
- A tenant-admin can target tenant-scoped groups for their tenant only.
- Global groups (
scope_type: "global") are super-admin-only.
Verify by listing memberships on the group after publish: if the persona's frontend model slug isn't there, scope rejection is the reason.
Avatar upload returns STORAGE_ERROR#
The S3 / Garage put failed. Causes:
- Bucket credentials misconfigured in module settings.
- Bucket region mismatch.
- Bucket disk full or quota exceeded.
The persona's avatar_url is not updated on failure — retry after fixing the underlying storage issue.
Persona slug collides#
PERSONA_SLUG_CONFLICT on create — another persona in the same tenant already uses this slug. Either reuse the existing persona or pick a different slug. Slugs are tenant-scoped, so the same slug can exist in another tenant.
Updates don't appear in invocations#
If PUT /personas/{id} returns success but live invocations still see the old behaviour:
- Verify the persona is actually published —
published: truein the GET response. - The frontend model is synced on save, but routing caches may need a few seconds. If it persists, restart the inference workers or rebuild the model cache.
system_promptis propagated viasystem_prompt_templateon the frontend model — the underlying model dispatch must honour template injection. Vendor backends that ignore system prompts (rare) won't reflect the change.
Persona invocations not metered against the right cost centre#
Accounting attributes usage to the frontend model that was called. For a published persona, that's the persona's frontend model — not the underlying vendor model. If you're grouping by vendor model and a persona's usage looks "missing", group by frontend model slug or filter for slugs prefixed with tenant/.