Troubleshooting
July 15, 2026 · View on GitHub
Symptoms and fixes, by deployment type. Start with the doctor script — it diagnoses most of what is listed here:
# Docker all-in-one
cd docker/all-in-one && ./doctor.sh
# Kubernetes
./helm/doctor.sh <release> <namespace> # defaults: teable opensandbox-system
Kubernetes
Pods stuck in Pending
Almost always storage: the PersistentVolumeClaims need a default StorageClass.
kubectl get pvc -n opensandbox-system # look for Pending claims
kubectl get storageclass # is any class marked (default)?
Either mark a class as default or set the storageClassName fields in your
values file (one per component, see helm/examples/values.example.yaml).
Certificates never become Ready
The chart requests certificates from a ClusterIssuer named letsencrypt-dns
by default. If you have not created it (or named yours differently), every
Certificate stays not-ready and ingress TLS serves a placeholder cert.
kubectl get clusterissuer # does letsencrypt-dns exist?
kubectl describe certificate -n opensandbox-system # issuer errors show here
Create the issuer (section 2 of helm/examples/values.example.yaml) or point
certificate.issuerName at yours. Two hosts are wildcards (*.app,
*.sandbox), so the issuer must use a DNS-01 solver.
Teable crashloops with NoSuchBucket after helm install --wait timed out
The storage buckets are created by a post-install hook, and Helm runs hooks
only after --wait returns -- while Teable cannot become ready without
the buckets. On a first install --wait therefore deadlocks until the
timeout, the release is marked failed, the hook never runs, and Teable
restarts with NoSuchBucket: teable-public. Install without --wait (see
the quick start note).
To recover an already-failed install, run the hooks once and clean them up (they are replayed outside of Helm, so Helm's hook cleanup does not apply -- the delete removes the finished hook Jobs and their temporary RBAC, keeping what they produced):
helm get hooks <release> -n opensandbox-system | kubectl apply -f -
kubectl wait --for=condition=complete job/<release>-minio-init -n opensandbox-system --timeout=5m
helm get hooks <release> -n opensandbox-system | kubectl delete -f - --ignore-not-found
opensandbox-server in CrashLoopBackOff: BatchSandbox template file not found
Your values override configToml (which references
/etc/opensandbox/batchsandbox-template.yaml) but leave
opensandbox-server.server.batchSandboxTemplate empty, so the file is never
mounted. Set the template back (the chart ships a working default), or remove
the reference from your custom configToml.
CreateContainerConfigError: secret "git-registry-jwt" not found
The chart generates this signing keypair in a pre-install hook. If you set
gitRegistry.jwtSecret.create: false, you must create the Secret yourself:
openssl genpkey -algorithm ed25519 -out jwt.key
openssl pkey -in jwt.key -pubout -out jwt.pub
kubectl -n opensandbox-system create secret generic git-registry-jwt \
--from-file=private=jwt.key --from-file=public=jwt.pub
helm upgrade fails with Apply failed with 1 conflict ... "kubectl-set"
You swapped an image with kubectl set image, and Helm 4 (server-side apply)
refuses to take the field back. Add --force-conflicts to the upgrade —
combined with -f helm/examples/images.values.yaml this re-pins the images
and puts Helm back in charge:
helm upgrade <release> helm/teable-infra -n opensandbox-system \
--reuse-values --server-side=true --force-conflicts \
-f helm/examples/images.values.yaml
Seeing forceConflicts enabled when serverSideApply disabled instead? Your
release history was installed with client-side apply; --server-side=true
(included above) switches it over.
Sandbox previews return 502
A 502 from https://<id>-<port>.sandbox.<baseDomain> means routing works but
nothing inside the sandbox listens on that port — check the app running in the
sandbox. If the host does not resolve, the *.sandbox.<baseDomain> DNS
record is missing.
AI features in Teable return errors
Teable reaches the runtime plane at https://infra.<baseDomain>. Check the
chain in order:
kubectl exec deploy/<release>-teable -n opensandbox-system -- \
sh -c 'wget -q -O- https://infra.<baseDomain>/api/health' # DNS + ingress + TLS
kubectl logs deploy/<release>-teable -n opensandbox-system | tail -50
A TLS verification error here means the infra certificate is not trusted by the Teable pod — see the certificates section above.
AI sessions fail right after starting: self-signed certificate in certificate chain
The stack is healthy and the UI works, but sandboxes reject the callback to
your Teable/infra hosts (SELF_SIGNED_CERT_IN_CHAIN,
UNABLE_TO_VERIFY_LEAF_SIGNATURE, or builds failing on git push with
SSL certificate problem). Your hosts serve certificates from a private CA
that the sandboxes do not trust — mount the root CA into the sandbox template:
see helm/private-ca.md.
Docker all-in-one
./doctor.sh covers the mainline failures (entry routing, /v1 split,
storage, sandbox engine). Two frequent ones:
Browser preview URLs do not resolve (server)
The *.sandbox.<BASE_DOMAIN> and *.app.<BASE_DOMAIN> wildcard DNS records
are missing — both must point at the machine, DNS-only (no proxy).
Certificate issuance fails on first start (server)
CLOUDFLARE_API_TOKEN lacks the Zone/DNS edit permission, or the DNS records
point somewhere else. Check docker compose logs caddy for the ACME error.
doctor entry checks return 000 on the machine itself (server)
Cloud VMs usually cannot reach their own public IP (GCP, for example, does not
hairpin NAT), so every https://<your-domain> check fails with 000 when run
on the machine -- while the deployment is perfectly reachable from outside.
In-stack traffic is unaffected (containers reach the entry through an internal
network alias). Either verify from your workstation, or point the two
non-wildcard hosts at the local entry and re-run:
echo "127.0.0.1 <BASE_DOMAIN> infra.<BASE_DOMAIN>" | sudo tee -a /etc/hosts
./doctor.sh
S3 tools cannot connect through infra.<BASE_DOMAIN>
The entry proxies object paths only (/<bucket>/… -- exactly what
presigned upload/download URLs use, which is all the platform needs). The
bucket-management API (list buckets, etc.) is not routed, so mc alias set
and similar clients fail against the entry; point them at MinIO directly
(SSH tunnel) for admin tasks.