{"record":{"id":"42a0bc410b7c12ac","repo":"restic/restic","slug":"feature-flag-s3-restore-is-required-to-use-o-s","errorCode":null,"errorMessage":"feature flag `s3-restore` is required to use `-o s3.enable-restore=true`","messagePattern":"feature flag `s3-restore` is required to use `-o s3\\.enable-restore=true`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/s3/s3.go","lineNumber":57,"sourceCode":"\ntype warmupStatus int\n\nconst (\n\twarmupStatusCold warmupStatus = iota\n\twarmupStatusWarmingUp\n\twarmupStatusWarm\n\twarmupStatusLukewarm\n)\n\nfunc NewFactory() location.Factory {\n\treturn location.NewHTTPBackendFactory(\"s3\", ParseConfig, location.NoPassword, Create, Open)\n}\n\nfunc open(cfg Config, rt http.RoundTripper) (*s3, error) {\n\tdebug.Log(\"open, config %#v\", cfg)\n\n\tif cfg.EnableRestore && !feature.Flag.Enabled(feature.S3Restore) {\n\t\treturn nil, fmt.Errorf(\"feature flag `s3-restore` is required to use `-o s3.enable-restore=true`\")\n\t}\n\n\tif cfg.MaxRetries > 0 {\n\t\tminio.MaxRetry = int(cfg.MaxRetries)\n\t}\n\n\tcreds, err := getCredentials(cfg, rt)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"s3.getCredentials\")\n\t}\n\n\toptions := &minio.Options{\n\t\tCreds:     creds,\n\t\tSecure:    !cfg.UseHTTP,\n\t\tRegion:    cfg.Region,\n\t\tTransport: rt,\n\t}\n","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/restic/restic/blob/a80be1478a4c537f8396e0db2b05120aa78f11e0/internal/backend/s3/s3.go#L39-L75","documentation":"The S3 backend refuses to start because the option -o s3.enable-restore=true was set while the 's3-restore' feature flag is disabled. Restore-on-read is experimental, so the option is gated behind its feature flag.","triggerScenarios":"Calling restic with -o s3.enable-restore=true (or the equivalent Config.EnableRestore in library code) on a restic version where the s3-restore flag defaults to off.","commonSituations":"Copy-pasted options from documentation of a newer/older restic; embedding restic and setting EnableRestore without toggling the flag; option carried in a wrapper script after a restic upgrade changed flag defaults.","solutions":["Enable the feature flag together with the option: pass --features s3-restore (or set the RESTIC_FEATURES environment variable to include s3-restore).","Or remove -o s3.enable-restore=true if restore-on-read is not needed.","Run 'restic features' to list flags and their current default state.","Check the changelog: once the feature stabilizes the flag gate is removed."],"exampleFix":"// before\nrestic -r s3:... backup -o s3.enable-restore=true\n// after\nrestic -r s3:... backup --features s3-restore -o s3.enable-restore=true","handlingStrategy":"validation","validationCode":"if cfg.EnableRestore && !feature.Flag.Enabled(feature.S3Restore) {\n    return errors.New(\"enable the s3-restore feature flag (RESTIC_FEATURES=s3-restore) before s3.enable-restore=true\")\n}","typeGuard":null,"tryCatchPattern":"_, err := s3.Create(ctx, cfg, rt)\nif err != nil && strings.Contains(err.Error(), \"s3-restore\") {\n    return fmt.Errorf(\"%w - add --features s3-restore or unset s3.enable-restore\", err)\n}","preventionTips":["Check 'restic features' output before using experimental S3 options.","Keep options and feature flags versioned together in the backup script.","Re-read the changelog on restic upgrades for flag graduation/removal."],"tags":["s3","feature-flag","config","validation"],"backgroundTag":null,"analyzedSha":"a80be1478a4c537f8396e0db2b05120aa78f11e0","analyzedAt":"2026-08-15T15:30:29.928Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}