{"record":{"id":"498542f51f5eea27","repo":"kopia/kopia","slug":"unsupported-put-blob-option","errorCode":null,"errorMessage":"unsupported put-blob option","messagePattern":"unsupported put-blob option","errorType":"exception","errorClass":"ErrUnsupportedPutBlobOption","httpStatus":null,"severity":"warning","filePath":"repo/blob/storage.go","lineNumber":38,"sourceCode":"var ErrSetTimeUnsupported = errors.New(\"SetTime is not supported\")\n\n// ErrInvalidRange is returned when the requested blob offset or length is invalid.\nvar ErrInvalidRange = errors.New(\"invalid blob offset or length\")\n\n// InvalidCredentialsErrStr is the error string returned by the provider\n// when a token has expired.\nconst InvalidCredentialsErrStr = \"The provided token has expired\"\n\n// ErrInvalidCredentials is returned when the token used for\n// authenticating with a storage provider has expired.\nvar ErrInvalidCredentials = errors.Errorf(InvalidCredentialsErrStr)\n\n// ErrBlobAlreadyExists is returned when attempting to put a blob that already exists.\nvar ErrBlobAlreadyExists = errors.New(\"blob already exists\")\n\n// ErrUnsupportedPutBlobOption is returned when a PutBlob option that is not supported\n// by an implementation of Storage is specified in a PutBlob call.\nvar ErrUnsupportedPutBlobOption = errors.New(\"unsupported put-blob option\")\n\n// ErrNotAVolume is returned when attempting to use a Volume method against a storage\n// implementation that does not support the intended functionality.\nvar ErrNotAVolume = errors.New(\"unsupported method, storage is not a volume\")\n\n// ErrUnsupportedObjectLock is returned when attempting to use an Object Lock specific\n// function on a storage implementation that does not have the intended functionality.\nvar ErrUnsupportedObjectLock = errors.New(\"object locking unsupported\")\n\n// ApplicationID is sent to storage providers as metadata in the User-Agent of requests.\n// It is used to identify the application making the request.\nvar ApplicationID = \"kopia\"\n\n// Bytes encapsulates a sequence of bytes, possibly stored in a non-contiguous buffers,\n// which can be written sequentially or treated as a io.Reader.\ntype Bytes interface {\n\tio.WriterTo\n","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/kopia/kopia/blob/82495e54b584c1ef6073c9e1be048f57f8aef078/repo/blob/storage.go#L20-L56","documentation":"ErrUnsupportedPutBlobOption is a sentinel in repo/blob/storage.go returned when a PutBlob call carries an option the Storage implementation does not support, such as retention (Object Lock) settings or DoNotRecreate. It lets backends advertise capability limits instead of silently ignoring options.","triggerScenarios":"PutBlob with PutOptions.HasRetentionOptions() on a backend without object-lock support, or with DoNotRecreate=true on a backend that cannot honor it; internal/blobtesting/map.go wraps it with 'blob-retention'/'do-not-recreate' context.","commonSituations":"Syncing to or writing on S3-compatible stores lacking Object Lock; providers that always allow recreate; tests/providervalidation that detect and accept this sentinel as 'feature not supported here'.","solutions":["Detect and drop the unsupported option: on errors.Is(err, blob.ErrUnsupportedPutBlobOption), retry PutBlob without retention/DoNotRecreate.","Use a backend supporting the feature (e.g. S3 with Object Lock enabled) if retention is mandatory.","For DoNotRecreate, implement existence checks manually (GetMetadata first) instead of relying on the option.","Note providervalidation treats this sentinel as acceptable — your workflow may safely ignore it too."],"exampleFix":"// before\nif err := st.PutBlob(ctx, id, data, opts); err != nil { return err }\n// after\nif err := st.PutBlob(ctx, id, data, opts); err != nil {\n    if errors.Is(err, blob.ErrUnsupportedPutBlobOption) {\n        opts.RetentionPeriod = 0\n        opts.EncryptionKeyID = \"\"\n        return st.PutBlob(ctx, id, data, opts)\n    }\n    return err\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := st.PutBlob(ctx, id, data, opts); err != nil {\n    if errors.Is(err, blob.ErrUnsupportedPutBlobOption) {\n        opts.RetentionPeriod = 0 // retry without unsupported options\n        return st.PutBlob(ctx, id, data, opts)\n    }\n    return err\n}","preventionTips":["Probe provider capabilities with providervalidation before enabling retention features.","Only set retention options on backends known to support Object Lock (e.g. S3 with it enabled).","Centralize PutBlob calls in a helper that degrades options on this sentinel."],"tags":["blob-storage","compatibility","sentinel-error"],"backgroundTag":"unsupported-operation","analyzedSha":"82495e54b584c1ef6073c9e1be048f57f8aef078","analyzedAt":"2026-09-07T20:35:21.689Z","contentChangedAt":"2026-09-07T20:35:21.689Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}