usememos/memos · error
storage ID is required
Error message
storage ID is required
What it means
validateInstanceStorages (store/storage.go:464) checks each entry of setting.Storages during a storage-setting update; an entry that is nil or has an empty Id fails with errors.New("storage ID is required"). Storage IDs are the stable identity used by DefaultStorageId, attachment references, and namespace-change re-identification, so an ID-less entry would break resolution. NormalizeInstanceStorageSetting normally guarantees IDs, which is why only raw canonical update requests are validated explicitly (storage.go:107-115).
Source
Thrown at store/storage.go:465
setting.S3Config = proto.CloneOf(storage.GetS3Config())
return
}
// Keep the most recently configured S3 storage available to legacy
// attachments that predate both storage IDs and embedded configurations.
for _, configuredStorage := range setting.Storages {
if configuredStorage.GetS3Config() != nil {
setting.S3Config = proto.CloneOf(configuredStorage.GetS3Config())
return
}
}
setting.S3Config = nil
}
func validateInstanceStorages(setting *storepb.InstanceStorageSetting) error {
seenIDs := map[string]bool{}
for _, storage := range setting.Storages {
if storage == nil || storage.Id == "" {
return errors.New("storage ID is required")
}
if seenIDs[storage.Id] {
return errors.Errorf("duplicate storage ID %q", storage.Id)
}
seenIDs[storage.Id] = true
if storage.Type == storepb.StorageType_STORAGE_TYPE_UNSPECIFIED {
return errors.Errorf("storage %q type is required", storage.Id)
}
if storage.Type == storepb.StorageType_STORAGE_TYPE_S3 && storage.GetS3Config() == nil {
return errors.Errorf("storage %q S3 config is required", storage.Id)
}
}
if !seenIDs[setting.DefaultStorageId] {
return errors.Errorf("default storage %q is not configured", setting.DefaultStorageId)
}
return nil
}
View on GitHub (pinned to 14d757ce1f)
Solutions
- Give every storages[] entry a non-empty id (e.g. "s3-primary", "local") before sending the update; keep IDs stable across edits so attachments keep resolving.
- Send the canonical update path (storages list populated) rather than relying on legacy normalization, and validate IDs client-side first.
- After upgrading the server, re-fetch the current setting and echo its storage IDs back instead of constructing them from scratch.
Example fix
// before
setting.Storages = append(setting.Storages, &storepb.Storage{
Type: storepb.StorageType_STORAGE_TYPE_S3,
Config: &storepb.Storage_S3Config{S3Config: cfg}, // no Id
})
// after
setting.Storages = append(setting.Storages, &storepb.Storage{
Id: "s3-primary",
Type: storepb.StorageType_STORAGE_TYPE_S3,
Config: &storepb.Storage_S3Config{S3Config: cfg},
}) Defensive patterns
Strategy: validation
Validate before calling
func validStorages(setting *storepb.InstanceStorageSetting) error {
seen := map[string]bool{}
for _, s := range setting.GetStorages() {
if s == nil || s.GetId() == "" {
return errors.New("storage ID is required")
}
if seen[s.GetId()] {
return errors.Errorf("duplicate storage ID %q", s.GetId())
}
seen[s.GetId()] = true
}
return nil
}
// run before PrepareInstanceStorageSettingUpdate / the update request Type guard
func hasAllStorageIDs(setting *storepb.InstanceStorageSetting) bool {
for _, s := range setting.GetStorages() {
if s == nil || s.GetId() == "" {
return false
}
}
return true
} Prevention
- Always assign a human-stable id when adding a storages[] entry; never rely on the server to invent one.
- Echo IDs from a fresh GetWorkspaceSetting when editing, instead of hand-building the list.
- Validate the setting client-side with the same rules (non-empty unique IDs, type set, S3 config present for S3) to catch errors before the round trip.
When it happens
Trigger: Sending an UpdateWorkspaceSetting storage request whose storages[] includes a message with no id field (empty string) or a null list element; constructing an InstanceStorageSetting programmatically and appending an unconfigured &storepb.Storage{}.
Common situations: Clients that omit id assuming the server generates one; hand-built protobuf/JSON payloads from scripts or Terraform-like tooling; partial request snapshots replayed after a proto schema change renamed the id field; older client versions unaware that named storages require explicit IDs.
Related errors
- storage setting is required
- GENERAL instance setting is required
- failed to decode protobuf JSON; verify field names, value ty
- 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/74867d4a4abfaa15.
Report an issue: GitHub.