usememos/memos · error
storage setting is required
Error message
storage setting is required
What it means
PrepareInstanceStorageSettingUpdate (store/storage.go:88) normalizes and validates an incoming InstanceStorageSetting for a workspace/instance update; a nil incoming setting is a protocol-level mistake, so it fails fast with errors.New("storage setting is required") at line 90. The function then adopts preserved storages, validates IDs/types/S3 configs, and re-identifies storages whose physical namespace changed — none of which is meaningful without a setting object.
Source
Thrown at store/storage.go:90
if FindStorage(setting, setting.DefaultStorageId) == nil {
fallback := builtinStorage(storepb.StorageType_STORAGE_TYPE_LOCAL)
if len(setting.Storages) > 0 {
fallback = setting.Storages[0]
} else {
setting.Storages = append(setting.Storages, fallback)
}
setting.DefaultStorageId = fallback.Id
}
moveDefaultStorageFirst(setting)
synchronizeLegacyStorageFields(setting)
}
// PrepareInstanceStorageSettingUpdate preserves storages still referenced by
// existing attachments and assigns a new identity when a physical namespace changes.
func PrepareInstanceStorageSettingUpdate(incoming, existing *storepb.InstanceStorageSetting) error {
if incoming == nil {
return errors.New("storage setting is required")
}
if existing != nil {
NormalizeInstanceStorageSetting(existing)
}
// A request may reference a storage the server preserves without resending
// it; adopt the stored entry so the reference survives validation and
// normalization instead of being silently replaced by a fallback default.
if incoming.DefaultStorageId != "" && FindStorage(incoming, incoming.DefaultStorageId) == nil {
preserved := FindStorage(existing, incoming.DefaultStorageId)
if preserved == nil {
return errors.Errorf("default storage %q is not configured", incoming.DefaultStorageId)
}
incoming.Storages = append(incoming.Storages, proto.CloneOf(preserved))
}
legacyRequest := len(incoming.Storages) == 0
if !legacyRequest {View on GitHub (pinned to 14d757ce1f)
Solutions
- Always populate the storage_setting field in the UpdateWorkspaceSetting/instance-setting request, even when only its sub-fields change.
- Guard the call site: only invoke the prepare function when the incoming setting is non-nil, and skip the storage-branch otherwise.
- After upgrading memos, regenerate client stubs so an omitted storage_setting is distinguishable from an empty one.
Example fix
// before
setting := req.GetSetting().GetStorageSetting() // nil when field omitted
if err := store.PrepareInstanceStorageSettingUpdate(setting, existing); err != nil { return err }
// after
setting := req.GetSetting().GetStorageSetting()
if setting == nil {
return status.Errorf(codes.InvalidArgument, "storage setting is required")
}
if err := store.PrepareInstanceStorageSettingUpdate(setting, existing); err != nil { return err } Defensive patterns
Strategy: type-guard
Validate before calling
if req.GetSetting().GetStorageSetting() == nil {
return status.Errorf(codes.InvalidArgument, "storage setting is required")
}
// only then:
err := store.PrepareInstanceStorageSettingUpdate(req.GetSetting().GetStorageSetting(), existing) Type guard
func hasStorageSetting(req *v1.UpdateWorkspaceSettingRequest) bool {
return req.GetSetting() != nil && req.GetSetting().GetStorageSetting() != nil
} Try / catch
if err := store.PrepareInstanceStorageSettingUpdate(incoming, existing); err != nil {
if err.Error() == "storage setting is required" {
return status.Errorf(codes.InvalidArgument, "%v", err)
}
return status.Errorf(codes.Internal, "failed to prepare storage setting: %v", err)
} Prevention
- Always populate storage_setting in workspace setting update requests, even for unrelated field changes.
- Guard with GetStorageSetting() != nil before calling the prepare function.
- Regenerate proto stubs after server upgrades so omitted vs empty fields are handled correctly.
When it happens
Trigger: Calling PrepareInstanceStorageSettingUpdate(nil, existing) — e.g. an UpdateInstanceSetting/UpdateWorkspaceSetting handler that extracts the storage setting from the request and the request omitted the storage_setting field, leaving the extracted proto nil.
Common situations: API clients (or older SDK versions) sending a workspace setting update that only touches a non-storage field while the server code unconditionally prepares the storage portion; schema/proto drift after upgrading; hand-rolled integrations constructing the request protobuf incompletely.
Related errors
- storage ID is required
- Internal
- GENERAL instance setting is required
- storageSetting must be populated for key STORAGE
- storageSetting.s3Config is required for S3
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/e7c24cd07a4fb7b7.
Report an issue: GitHub.