Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Troubleshooting

Every kind carries a phase and a Ready or Complete condition whose reason names the situation and whose message gives the detail. Start there, then the operator log:

kubectl describe qc my-qdrant
kubectl get qb first -o jsonpath='{.status.error}{"\n"}'
kubectl logs -n qdrant-system deploy/qdrant-operator -f

Retries show up in the log as kopf TemporaryError lines with the reason and the thirty-second delay. Permanent failures write the phase Failed and the error into the status and stop.

QdrantCluster

SymptomMeaningWhat to do
Pending and stays thereThe Helm release is applied but pods are not readykubectl get pods -l app.kubernetes.io/instance=qdrant-<name>, then describe the pod that is not ready
No phase and no podsThe first helm upgrade --install failed before any status was written; the operator retriesLook for helm upgrade failed in the log. Common causes: a chart version that does not exist for that version, a config key the chart rejects, missing monitoring.coreos.com CRDs with a ServiceMonitor enabled
Pods PendingNo node fits or no volume can be boundkubectl describe pod: check resources, nodeSelector, affinity and the storage class
Pods CrashLoopBackOffQdrant rejects its configurationContainer logs; a typo under config lands in production.yaml verbatim
Upgrading for a long timeA rolling update is stuck on one podThe StatefulSet waits for each pod to be ready before the next; fix that pod

Only Pending, Upgrading and Running are set by the operator; a Helm error keeps the previous phase and is retried.

QdrantCollection

ReasonMeaning
CollectionReadyThe collection, its indexes and aliases match the spec
ImmutableFieldMismatchvectors, shardNumber or shardingMethod differ from the live collection; phase Degraded, nothing changed
retried: cluster not foundclusterRef names a QdrantCluster that does not exist yet
retried: cluster not ready/readyz on the Service does not answer 200
Failed with an HTTP errorQdrant rejected a request; the message carries Qdrant's response. Usually a field name Qdrant does not know inside hnsw, optimizers, quantization, strictMode or params

A 401 or 403 from Qdrant means the operator's API key does not match: it uses apiKey.secretRef or the generated qdrant-<name>-apikey Secret, and nothing else.

QdrantAccessKey

ReasonMeaning
TokenIssuedThe Secret holds a current token
JwtRbacDisabledThe cluster's apiKey.jwtRbac is false; phase Pending until it is turned on
ApiKeyMissingThe cluster has neither apiKey.secretRef nor autoGenerate; nothing to sign with
retried: cluster or Secret not foundclusterRef or the API key Secret does not exist yet

Qdrant answering 401 to a token that the operator reports as Ready means the token was signed with a different key than Qdrant runs with: the cluster's API key was rotated and Qdrant's pods have not restarted yet, or the other way round. status.keyFingerprint changes when the operator sees the new key; the pods pick it up on the roll helm upgrade triggers.

QdrantMigration

MessageMeaning
QdrantCluster ... not readyThe target does not answer /readyz; retried
Collections not present in sourcecollections names something the source does not list
Collection ... missing on target and createMissing is falseCreate the target collection first or allow creation
4xx from the source on points/scrollWrong or missing apiKeySecretRef, or a token without read access
TLS verification failedA source behind a private CA needs caSecretRef
Failed on upsert with a dimension errorThe target collection exists with a different vector size; rename via collectionMapping or drop it

A migration whose percentage runs past what you expect is counting against Qdrant's approximate pointsTotal; the final pointsCopied is exact.

QdrantBackup

PhaseMeaning
PendingWaiting for the cluster or the credentials Secret; retried every thirty seconds
InProgressSnapshots are being taken and uploaded
Completedmanifest.json written; s3Path and totalSize set
Failedstatus.error holds the first collection's error, status.collections each one's

Frequent causes of Failed:

  • Connection refused or timeout to a pod URL. The operator reaches nodes as qdrant-<name>-<i>.qdrant-<name>-headless.<ns>.svc.cluster.local. A NetworkPolicy between the operator namespace and the cluster namespace, or a replicas value higher than the pods that exist, produces this.
  • TLS certificate verification failed. With tls.enabled, the operator needs ca.crt in the TLS Secret, or a certificate from a CA in the system trust store, and the certificate must cover the headless pod names.
  • No space left on device from Qdrant. The snapshot did not fit on the node's volume. Enable snapshotPersistence or grow the data volume.
  • Access denied from the bucket. Check the credentials Secret, the bucket policy, and for MinIO endpoint plus forcePathStyle: true.

Deleting a Failed backup still removes what was uploaded.

QdrantBackupSchedule

SymptomMeaning
No backup at the expected timeThe slot is computed in UTC; check nextBackupTime. With Forbid, a still running backup blocks the slot, see activeBackup
One backup right after the operator restartedA catch-up for the most recent missed slot. Set startingDeadlineSeconds to skip stale slots
Old backups disappearingretentionPolicy pruned them, together with their objects in the bucket
Backups gone after deleting the scheduleThey were owned by the schedule and garbage-collected

QdrantRestore

MessageMeaning
QdrantBackup ... is InProgress, not CompletedRetried until the backup finishes
Backup was taken from N nodes but target cluster has MNode counts must match; create a target with N replicas
Collections not present in backupcollections names something the manifest does not have
Collection ... did not turn green in timeIndexing took more than one hour; the data is there, only the wait timed out
A node returns 4xx on snapshots/recoverThe node could not fetch the presigned URL. Nodes need network access to the bucket endpoint, and the URL expires after one hour

Operator pod

The pod runs as uid 1000 with a read-only root filesystem and Helm's cache directories under an emptyDir at /tmp. helm failures mentioning permission denied point at a policy that replaced that volume. The pod answers /healthz on port 8080; a restart loop there means kopf could not start, and the first log lines say why, typically RBAC on the CRDs or missing CRDs.

Turn the log up with --set operator.logLevel=DEBUG to see every helm command line and every Qdrant request the operator makes.