{"record":{"id":"2a24c53eb8df7e0e","repo":"restic/restic","slug":"config-file-already-exists-2a24c5","errorCode":null,"errorMessage":"config file already exists","messagePattern":"config file already exists","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/rest/rest.go","lineNumber":95,"sourceCode":"\tcerr := resp.Body.Close()\n\n\t// return first error\n\tif err != nil {\n\t\treturn errors.Errorf(\"drain: %w\", err)\n\t}\n\treturn cerr\n}\n\n// Create creates a new REST on server configured in config.\nfunc Create(ctx context.Context, cfg Config, rt http.RoundTripper, errorLog func(string, ...any)) (*Backend, error) {\n\tbe, err := Open(ctx, cfg, rt, errorLog)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t_, err = be.Stat(ctx, backend.Handle{Type: backend.ConfigFile})\n\tif err == nil {\n\t\treturn nil, errors.New(\"config file already exists\")\n\t}\n\n\turl := *cfg.URL\n\tvalues := url.Query()\n\tvalues.Set(\"create\", \"true\")\n\turl.RawQuery = values.Encode()\n\n\tresp, err := be.client.Post(url.String(), \"binary/octet-stream\", strings.NewReader(\"\"))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := drainAndClose(resp); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, &restError{backend.Handle{}, resp.StatusCode, resp.Status}","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/restic/restic/blob/a80be1478a4c537f8396e0db2b05120aa78f11e0/internal/backend/rest/rest.go#L77-L113","documentation":"The REST backend's Create (used by 'restic init') first opens the repository, stats the config file at ConfigFile, and refuses to proceed when it already exists. This protects the existing repository from being overwritten by a second init.","triggerScenarios":"Running 'restic -r rest:<url> init' when the REST server already has a 'config' file at the target; re-initializing after a partial earlier init; pointing the URL at an existing repo path/prefix.","commonSituations":"Scripts that run init unconditionally on every deployment; copying a repository to the server and then running init; wrong URL prefix so the request lands on an existing repository's namespace.","solutions":["Skip init when the repository exists: run 'restic -r ... snapshots' first and only init when it reports a non-existent repo.","If you truly want a fresh repo, remove or move the old one on the server (delete the config file or the whole prefix) before init.","Verify the URL points at the intended, empty path and does not reuse an existing prefix."],"exampleFix":"# before\nrestic -r rest:http://server:8000/myrepo init\n# -> config file already exists\n\n# after\nrestic -r rest:http://server:8000/myrepo snapshots || restic -r rest:http://server:8000/myrepo init","handlingStrategy":"validation","validationCode":"// check existence before init\n_, err := resticStatConfig(repoURL) // e.g. `restic -r <repo> cat config` equivalent\nif err == nil {\n\treturn errors.New(\"repository already initialized; skipping init\")\n}\n// safe to init","typeGuard":null,"tryCatchPattern":"err := be.Create(ctx, cfg, rt, nil)\nif err != nil {\n\tif strings.Contains(err.Error(), \"config file already exists\") {\n\t\t// treat as idempotent success or surface a clear message\n\t\tlog.Printf(\"repository at %s already exists\", cfg.URL)\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Make init scripts idempotent: probe for the config file first.","Never run init against a URL you cannot afford to lose; init refuses, but keep the habit."],"tags":["rest-backend","init","data-safety","configuration"],"backgroundTag":null,"analyzedSha":"a80be1478a4c537f8396e0db2b05120aa78f11e0","analyzedAt":"2026-08-15T15:30:29.928Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}