Skip to content

Troubleshooting deploy

Status: Current | Last reviewed: 2026-06-12

Helm install / upgrade failures and pod crash-loops.

Symptom: helm upgrade fails on schema validation

The chart has values schemas. A common cause: a per-service block expects a list of secret refs but you passed a string.

helm lint charts/trueserve-stack -f your-values.yaml

Read the line/column it points at and fix the YAML shape.

Symptom: Pod CrashLoopBackOff with "MASTER_ENCRYPTION_KEY missing"

The trueserve-master-key secret is not mounted, or the chart's secretRefs list does not include it for that service.

kubectl describe pod <pod> -n trueserve | grep -i secret
kubectl get secret trueserve-master-key -n trueserve

Fix: add the ref to the per-service block. See secrets-management.md.

Symptom: ai-manager 500s on /api/integrations

Postgres reachable but not initialized. The init-scripts/ are applied by the postgres init container; if you swapped to a managed Postgres, you must apply them yourself:

psql "$DATABASE_URL" -f deploy/init-scripts/000_full_schema.sql
for f in deploy/init-scripts/*.sql; do
  psql "$DATABASE_URL" -f "$f" || true
done

See overview.md.

Symptom: Ingress shows the chart's host but TLS doesn't issue

cert-manager logs:

kubectl logs -n cert-manager deploy/cert-manager --tail 200

Common causes: HTTP-01 challenge can't reach the server (firewall), or DNS hasn't propagated. Wait, retry, or fall back to a manual cert.

Symptom: Voice pods on default node pool

You set nodeSelector for media on app-tier pods, or you didn't set it on media pods. Check:

kubectl get pods -n trueserve -l app=rtpengine -o jsonpath='{.items[*].spec.nodeName}'

Should be a media pool node. Fix in values:

rtpengine:
  nodeSelector:
    node-pool: media
  tolerations:
    - key: media
      operator: Equal
      value: "true"
      effect: NoSchedule

Symptom: conversation-api can't reach object storage on AWS

All services ride the shared storage seam against S3-compatible endpoints (object-storage.md). Check:

  • STORAGE_BUCKET_<ROLE> is set for the role the failing service uses — the seam has no default bucket and raises loudly when it is missing.
  • STORAGE_REGION matches the bucket region (a wrong region answers 301 with no useful message).
  • A custom STORAGE_ENDPOINT (MinIO, GCS interop) also has STORAGE_FORCE_PATH_STYLE=true and includes the scheme.
  • IRSA pods have AWS_WEB_IDENTITY_TOKEN_FILE and AWS_ROLE_ARN, or static S3_ACCESS_KEY / S3_SECRET_KEY are mounted.
  • Tenant archive sinks that write to a different bucket have a valid integration with access_key / secret_key (or AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY) and non-secret sink config for bucket, prefix, endpoint, and region.

See also