{"record":{"id":"447ccd2dd5530679","repo":"weaviate/weaviate","slug":"backup-q-already-exists-at-q","errorCode":null,"errorMessage":"backup %q already exists at %q","messagePattern":"backup %q already exists at %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"usecases/backup/scheduler.go","lineNumber":867,"sourceCode":"\t\tknown[r] = struct{}{}\n\t}\n\tfor _, r := range roles {\n\t\tif _, ok := known[r]; !ok {\n\t\t\treturn nil, fmt.Errorf(\"role %q in 'includeRoles' does not exist\", r)\n\t\t}\n\t}\n\tif len(roles) == 0 {\n\t\treturn nil, fmt.Errorf(\"no roles match 'includeRoles' %v\", includeRoles)\n\t}\n\treturn roles, nil\n}\n\nfunc (s *Scheduler) checkIfBackupExists(ctx context.Context, store coordStore, req *BackupRequest) error {\n\tdestPath := store.HomeDir(req.Bucket, req.Path)\n\t// there is no backup with given id on the backend, regardless of its state (valid or corrupted)\n\tmeta, err := store.Meta(ctx, GlobalBackupFile, req.Bucket, req.Path)\n\tif err == nil && meta.Status != backup.Cancelled {\n\t\treturn fmt.Errorf(\"backup %q already exists at %q\", req.ID, destPath)\n\t}\n\n\tif !errors.As(err, &backup.ErrNotFound{}) {\n\t\treturn fmt.Errorf(\"check if backup %q exists at %q: %w\", req.ID, destPath, err)\n\t}\n\treturn nil\n}\n\nfunc (s *Scheduler) validateRestoreRequest(ctx context.Context, store coordStore, req *BackupRequest) (*backup.DistributedBackupDescriptor, error) {\n\tif !store.backend.IsExternal() && s.restorer.nodeResolver.NodeCount() > 1 {\n\t\treturn nil, errLocalBackendDBRO\n\t}\n\tif len(req.Include) > 0 && len(req.Exclude) > 0 {\n\t\treturn nil, errIncludeExclude\n\t}\n\t// Check for duplicates in raw patterns early (before backend operations)\n\tif dup := findDuplicate(req.Include); dup != \"\" {\n\t\treturn nil, fmt.Errorf(\"class list 'include' contains duplicate: %s\", dup)","sourceCodeStart":849,"sourceCodeEnd":885,"githubUrl":"https://github.com/weaviate/weaviate/blob/75aa4b6d11f8818305aafd4440b4e32794f7ca04/usecases/backup/scheduler.go#L849-L885","documentation":"During backup validation the coordinator found existing backup metadata (backup_config.json) at the destination bucket/path whose status is not Cancelled — meaning a backup with that ID (or any backup occupying that slot) already exists in a valid/completed/failed-in-progress state. The scheduler refuses to overwrite; backups are identified by their destination slot, so a new backup must use a fresh ID or path.","triggerScenarios":"Calling the backup API (create) with an ID whose destination (bucket+path) already holds metadata from a previous backup that succeeded, is running, or failed but wasn't cancelled. Also hit when re-running a backup job that already completed.","commonSituations":"Re-running a scheduled backup script with the same backup ID without cleanup; retrying after a failed run that left recoverable metadata; two pipelines racing with the same ID; restoring from an old config that still references a used ID.","solutions":["Choose a new, unique backup ID (or a different path) and retry.","If the previous backup is no longer needed, delete/cancel it first (cancel moves it to Cancelled status, which this check permits to be overwritten), then re-run.","If the slot contains stale/corrupted metadata from an aborted operation, remove the backup slot at destPath on the backend storage, then retry."],"exampleFix":"// before\nPOST /v1/backups/s3 {\"id\": \"daily-backup\"}  // already exists\n// after\nPOST /v1/backups/s3 {\"id\": \"daily-backup-2026-09-04\"}  // unique ID","handlingStrategy":"validation","validationCode":"meta, err := store.Meta(ctx, \"backup_config.json\", bucket, path)\nslotFree := err != nil || meta.Status == \"CANCELLED\"\nif !slotFree {\n    return fmt.Errorf(\"slot %s/%s occupied; use a new backup ID\", bucket, path)\n}","typeGuard":null,"tryCatchPattern":"if err := createBackup(req); err != nil && strings.Contains(err.Error(), \"already exists at\") {\n    // cancel/delete the old backup or pick a new ID before retrying\n    newID := req.ID + \"-\" + time.Now().UTC().Format(\"20060102-150405\")\n    req.ID = newID\n    return createBackup(req)\n}","preventionTips":["Use time- or version-suffixed backup IDs in automation","Cancel the prior backup before reusing its slot","Check backup status before re-running scheduled jobs","Never share one backup ID across concurrent pipelines"],"tags":["backup","idempotency","conflict","storage"],"backgroundTag":"backup-already-exists","analyzedSha":"75aa4b6d11f8818305aafd4440b4e32794f7ca04","analyzedAt":"2026-09-04T14:58:20.392Z","contentChangedAt":"2026-09-04T14:58:20.392Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}