{"record":{"id":"7abb6e9692edd4e2","repo":"vitessio/vitess","slug":"attemptrecoveryregistration-active-recovery-id","errorCode":null,"errorMessage":"AttemptRecoveryRegistration: Active recovery (id:%v) in the cluster %s:%s for %s","messagePattern":"AttemptRecoveryRegistration: Active recovery \\(id:(.+?)\\) in the cluster (.+?):(.+?) for (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtorc/logic/topology_recovery_dao.go","lineNumber":136,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttopologyRecovery.ID = lastInsertID\n\treturn topologyRecovery, nil\n}\n\n// AttemptRecoveryRegistration tries to add a recovery entry; if this fails that means recovery is already in place.\nfunc AttemptRecoveryRegistration(analysisEntry *inst.DetectionAnalysis) (*TopologyRecovery, error) {\n\t// Check if there is an active recovery in progress for the cluster of the given instance.\n\trecoveries, err := ReadActiveClusterRecoveries(analysisEntry.AnalyzedKeyspace, analysisEntry.AnalyzedShard)\n\tif err != nil {\n\t\tlog.Error(err.Error())\n\t\treturn nil, err\n\t}\n\tif len(recoveries) > 0 {\n\t\terrMsg := fmt.Sprintf(\"AttemptRecoveryRegistration: Active recovery (id:%v) in the cluster %s:%s for %s\", recoveries[0].ID, analysisEntry.AnalyzedKeyspace, analysisEntry.AnalyzedShard, recoveries[0].AnalysisEntry.Analysis)\n\t\tlog.Error(errMsg)\n\t\treturn nil, errors.New(errMsg)\n\t}\n\n\ttopologyRecovery := NewTopologyRecovery(*analysisEntry)\n\n\ttopologyRecovery, err = writeTopologyRecovery(topologyRecovery)\n\tif err != nil {\n\t\tlog.Error(err.Error())\n\t\treturn nil, err\n\t}\n\treturn topologyRecovery, nil\n}\n\n// ResolveRecovery is called on completion of a recovery process and updates the recovery status.\n// It does not clear the \"active period\" as this still takes place in order to avoid flapping.\n// The recovery_detection row is NOT deleted here: if the recovery failed, the problem is still\n// active and the detection row must survive so subsequent retry attempts share the same\n// detection_id. The incident boundary is established by resolveRecovery when IsSuccessful=true\n// (i.e. a new primary was promoted via ERS/PRS); at that point the detection row is deleted so","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtorc/logic/topology_recovery_dao.go#L118-L154","documentation":"AttemptRecoveryRegistration found an already-active (unresolved) topology recovery in the same keyspace/shard, so it refuses to register a duplicate concurrent recovery. Only one recovery per cluster shard may run at a time.","triggerScenarios":"Multiple analysis entries (primary failure, replica issues) trigger recoveries for the same cluster simultaneously; a prior recovery is still marked active in the vtorc database because it never completed or was not marked done.","commonSituations":"Stale recovery rows in the _vt.recovery table after vtorc crash; overlapping detections such as DeadPrimary plus PrimaryReadOnly hitting fixPrimary and runPlannedReparentOp at once; multiple vtorc instances competing.","solutions":["Wait for the active recovery to complete and re-check","Inspect vtorc's recovery table (audit/recovery UI) for a stuck recovery ID and resolve it","Ensure only one vtorc instance is active for the cluster (leader election working)","If the active recovery is genuinely stale/crashed, clean it up per your vtorc maintenance procedure"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"_, err := logic.AttemptRecoveryRegistration(ctx, entry, expireTime, ActionRecoverPrimary)\nif err != nil && strings.Contains(err.Error(), \"Active recovery\") {\n    // another recovery owns this shard; back off\n    return nil\n}\nif err != nil { return err }","preventionTips":["Run a single vtorc leader per cluster and verify leader election","Monitor for recoveries stuck in active state and alert on them","Clean up stale recovery rows after vtorc crashes"],"tags":["vtorc","recovery","concurrency","lock-contention"],"backgroundTag":"recovery-already-in-progress","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}