Skip to main content
Back up the volumes below yourself, check health with bash install.sh status, and find fixes by symptom under Troubleshooting.

Backups

The chart creates no backup job. Back up these volumes yourself, for example with AWS Backup or EBS snapshots: External PostgreSQL or Redis use the managed service’s backups. Migrations are forward-only, so a schema rollback needs a restore.

Monitoring

No metrics stack or ServiceMonitor ships. The xpander-smoke Job logs smoke passed: every required component serves when all components answer, and bash install.sh status gives a read-only verdict. Scrape the services with your own stack for metrics.

Troubleshooting

Every failure prints FIX: (the repair) and RERUN: (your non-interactive one-liner, secrets as placeholders). The installer is idempotent: fix, paste the rerun line, and it resumes. The checklist stops most problems before anything changes. Scripts read the exit code (Automation & CI), and bash install.sh status gives a read-only verdict.

Mirroring and registries

ECR refuses pushes to repositories that do not exist. The current image_sync.sh creates them (with AWS CLI credentials). Refresh your copy:
On an older copy, pre-create the repository and re-run (copied images are skipped):
authentication required even though docker login works: skopeo cannot read Docker Desktop’s credential store. The current image_sync.sh logs in to ECR itself (aws ecr get-login-password | skopeo login --username AWS --password-stdin). For other registries, pass credentials:
401 from auth.docker.io (incorrect username or password): the credential is the organization username xpanderaihub plus the token from your email, not a personal username. Re-run with --xpander-registry-user xpanderaihub --xpander-registry-token <token>. Still refused? Ask xpander to re-issue the token with repository-read and image-pull access.
Pod events show manifest unknown, or the checklist reports:
The mirror lacks that repository at the pinned tag. Tags differ per image, so one stale repo is enough. Re-run the mirroring (in-wizard or image_sync.sh), then check the exact coordinate:

Cluster and network

An image reference still points at docker.io instead of your mirror. Install with --registry <your-mirror>/<path>, and make sure the nodes reach the mirror (on an ECR-only sealed VPC: ecr.api + ecr.dkr endpoints, the S3 gateway endpoint, ECR read on the node role). Find the reference:
(On a mixed cluster: exec format error.) xpander images are amd64-only, so ARM/Graviton (t4g, m7g, c7g, …) cannot run them. Add an amd64 node group. Only for genuinely arm64 images: --set 'preflight.allowedArchitectures[0]=arm64'.
The ingress Service’s events show:
A sealed VPC has no public subnets and the private ones lack ELB role tags. Tag them and annotate the Service:
Or skip the load balancer: use the VPN, or kubectl -n xpander port-forward svc/ui 8080:80.
The probe ran before the namespace existed (fixed in current installers). Refresh (curl -fsSL https://charts.xpander.ai/install.sh) or create the namespace and re-run:
Unbound PVCs (kubectl -n xpander describe pvc) mean no usable RWO StorageClass or too little capacity for the footprint. Check kubectl get storageclass, pass --storage-class <name>, and look for FailedScheduling in kubectl -n xpander get events --sort-by=.lastTimestamp.
The browser console shows:
Charts before 0.6.0 did not derive the UI’s origins from the domain. Upgrade with bash install.sh upgrade, or set ui.env (VITE_SUPABASE_URL, VITE_CHAT_BACKEND_URL, …) yourself.
chat.<domain> opens but sign-in or API calls fail: only one of the published hosts has a record. Add a wildcard *.<domain>, or records for chat, api, agent-controller, supabase, webhook, client-auth and actions (or your <name>.ingress.host values). Check what is published:

Install and upgrade

The installer refuses a stuck release, and install.sh upgrade needs deployed. Recover first:
Then paste your RERUN: line. pending-install (an interrupted first install) is fixed with helm uninstall. xpander-generated-keys survives it, so the reinstall keeps the same keys.
Load a complete latest release, mirror its images, and retry with that manifest. For direct Helm, pass both generated values files, release values last. Never guess a shared image tag.
The installer checks the two xpander-license/v2 files (or the legacy v1 file) and the --org binding. Preflight repeats it with the Ed25519 signature, and deployment-manager repeats it at boot. GET /v1/license/status answers valid, expiring, grace or expired.Expired: the installer warns License expired on <date> - preflight will refuse the install. Replace only activation.json in the Secret with the renewed file and redeploy:
Then run install.sh upgrade or your pipeline’s re-install (the Secret checksum rolls the services). Keep the --set global.license.installKey/activationKey/publicKey flags if you pass your own --values (The License). A legacy v1 install swaps its license.json the same way.
Usually the agent holds a connection to an API connector that never finished (status faulty, no spec). The agents pod log shows a pydantic error on ConnectedConnector.open_api_spec_id. Recover from the in-cluster Supabase database:
Reload the agent in every open tab before saving it again: a stale tab writes the dead connection back.
The installer printed the Job’s last 30 lines. Dig deeper:
org-seed needs --org-name and --admin-email whenever Supabase is on. A hand-driven helm upgrade without them fails at render time.
A username with password: "" beside it overrides the generated password with an empty string. Remove the empty password: key: an absent key is preserved, "" wins.
On releases before the single-provider generator, a missing OpenAI key made the dialog show “The AI enrichment pipeline reported a failure” although the skill finished seconds later. Check the skills list before retrying. Upgrading fixes it.
You upgraded before mirroring (typically manifest unknown). Mirror the target release and re-run the upgrade. --atomic already rolled back the failed attempt.
--reuse-values resurrected a stale edge-runtime image pin. Upgrade with your real values files (as install.sh upgrade does), or clear it once:
Better: pin the mirrored edge-functions build (--edge-functions-tag).
Hybrid and Air-Gapped cannot be upgraded into each other. Use another --release / --namespace, or helm uninstall xpander -n xpander first.
Piped into bash, the run is non-interactive and needs --org, --install-license-file and --activation-license-file (or --license-file for v1). It exits with code 2 and a rerun line. For the wizard, download the script and run bash install.sh --edition airgap.