Redis Cluster migration fails on ch-migrations: missing redis_cluster_node_uris key
Last updated: October 30, 2026
Symptom
When switching a self-hosted LangSmith Helm deployment's Redis from a standalone external instance to an external Redis Cluster, helm upgrade fails on the ch-migrations job with:
CreateContainerConfigError(couldn't find key redis_cluster_node_uris in Secret langsmith/<release>-langsmith-redis)This happens even though redis.external.cluster in your values file looks correct.
Cause
ch-migrations runs as a pre-upgrade hook, which Helm executes before it reconciles the rest of the release's manifests. The Redis Secret that supplies redis_cluster_node_uris and redis_cluster_password is an ordinary (non-hook) chart resource, and the chart only auto-generates it when you haven't set redis.external.existingSecretName or redis.disableSecretCreation.
Because that generated Secret is applied along with the rest of the release, and the pre-upgrade hook runs before that happens, a migration from standalone Redis to Redis Cluster done in the same upgrade can hit a race: the hook job starts and reads the old standalone-Redis secret content, because the chart hasn't written the new cluster keys into the Secret yet. The job then fails looking for a key that isn't there.
This is unrelated to Fleet's Redis configuration (fleet.redis.external, using connectionUrl/existingSecretName and the redis_connection_url key). Fleet has its own separate Redis configuration surface and doesn't need any changes to fix this.
Resolution
Avoid the Secret-update-ordering race by pre-creating the cluster Secret yourself instead of letting the chart generate it mid-upgrade.
Create a Kubernetes Secret in the LangSmith namespace containing:
redis_cluster_node_uris: a JSON-array string of the cluster's node URIs.redis_cluster_password: the cluster password, or an empty string if authentication is disabled (the chart references this key even when empty).
Point the chart at your Secret instead of letting it generate its own:
redis: external: enabled: true existingSecretName: <your-secret-name> cluster: enabled: true tlsEnabled: true # set to false only if the Redis cluster does not use TLSSetting
existingSecretNamesuppresses the chart-generated Redis Secret, so the hook job always has the right keys available regardless of apply order.Leave Fleet's Redis settings (
fleet.redis.*) unchanged. They're a separate configuration surface and not part of this failure.Retry the Helm upgrade once the Secret exists.
This configuration surface (redis.external.cluster.nodeUrisSecretKey / passwordSecretKey, default key names redis_cluster_node_uris / redis_cluster_password) applies to chart versions before v0.18. Starting in v0.18 (through v0.19), it's deprecated in favor of redis.external.connectionUrlSecretKey.