Troubleshooting
Start here
kubectl get pods,job -n presponsieve
kubectl logs -n presponsieve deploy/presponsieve --tail=100
kubectl get events -n presponsieve --sort-by=.lastTimestamp | tail -20
The install fails before pods start
That is the migration hook, and it is working as designed.
kubectl logs -n presponsieve job/presponsieve-migration
Usually the database is unreachable, the role lacks CREATE, or the database does not exist. The chart fails cleanly here rather than starting pods against a missing schema.
Pods will not start
ImagePullBackOff. Add an image pull secret if the GHCR package is private to you.
CrashLoopBackOff. Check the license and the content key first.
kubectl logs -n presponsieve deploy/presponsieve --previous | head -50
A license signature failure usually means the token was truncated or gained a trailing newline. Use printf %s, not echo, when writing it into a secret.
A model asset failure means MODEL_CONTENT_KEY is missing or does not match the key the image was built with. If your license embeds the content key, MODEL_CONTENT_KEY should be blank rather than wrong.
Startup probe failures. The startup budget is roughly 150 seconds, covering CSV parse and database connect. If you are exceeding it, the database is slow to reach rather than the app being slow to boot.
Login loops
In order of likelihood:
SESSION_SECRETunset with more than one replica. The callback lands on a pod that cannot validate the cookie. Intermittent, and looks like an identity provider fault.- Plain HTTP.
AUTH_COOKIE_SECUREdefaults to"1", so the cookie will not persist. Common when testing through a port-forward. - The load balancer is stripping
Set-Cookie.
invalid issuer at sign-in
curl -s https://your-idp/.well-known/openid-configuration | jq .issuer
That must match oidc.issuerUrl exactly. On Entra, use the v2.0 issuer.
HTML 502 on long transcripts
The load balancer timed out, not the app. Nothing appears in the application logs, because the app never saw the disconnect.
- GKE:
BackendConfigwithtimeoutSec: 600. The default is 30 seconds - nginx:
proxy-read-timeout: "600" - ALB:
idle_timeout.timeout_seconds=600
HTML 413 on upload
nginx's 1MB default body size, returned by nginx rather than the app.
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
Reports generate but downloads fail
On GKE, this is almost always the signing binding. Workload Identity credentials carry no private key, so V4 URL signing goes through IAM signBlob.
The service account needs roles/iam.serviceAccountTokenCreator on itself, and GCS_SIGNER_SERVICE_ACCOUNT must equal the account in serviceAccount.annotations.
Everything else works, which is what makes this one hard to spot.
Uploads hang rather than failing
A default-deny egress policy without a rule for your storage endpoint. The connection is dropped rather than refused, so the client waits.
Chat returns 503
Chat is temporarily unavailable. Please set OPENAI_API_KEY.
Expected behaviour without the key. Analysis still works and returns structured output; only prose rendering and chat need it. See Rendering.
Analysis returns numbers but no prose
Also expected without OPENAI_API_KEY. The response carries a note saying rendering is unavailable. This is a supported configuration, not a fault.
Gathering information for support
kubectl get pods,job -n presponsieve -o wide
kubectl logs -n presponsieve deploy/presponsieve --tail=200
helm get values presponsieve -n presponsieve
helm history presponsieve -n presponsieve
Redact secrets before sending. helm get values will not contain them if you used app.existingSecret, which is one more reason to.