{"record":{"id":"5e2da63930347761","repo":"usememos/memos","slug":"storagesetting-must-be-populated-for-key-storage","errorCode":null,"errorMessage":"storageSetting must be populated for key STORAGE","messagePattern":"storageSetting must be populated for key STORAGE","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store/deployment_config.go","lineNumber":234,"sourceCode":"\tif config.FieldMapping == nil || strings.TrimSpace(config.FieldMapping.Identifier) == \"\" {\n\t\treturn errors.New(\"config.oauth2Config.fieldMapping.identifier is required\")\n\t}\n\treturn nil\n}\n\nfunc validateAndNormalizeDeploymentInstanceSetting(setting *storepb.InstanceSetting) error {\n\tswitch setting.Key {\n\tcase storepb.InstanceSettingKey_GENERAL:\n\t\tif setting.GetGeneralSetting() == nil {\n\t\t\treturn errors.New(\"generalSetting must be populated for key GENERAL\")\n\t\t}\n\t\tif offset := setting.GetGeneralSetting().WeekStartDayOffset; offset < -1 || offset > 6 {\n\t\t\treturn errors.New(\"generalSetting.weekStartDayOffset must be between -1 and 6\")\n\t\t}\n\tcase storepb.InstanceSettingKey_STORAGE:\n\t\tstorage := setting.GetStorageSetting()\n\t\tif storage == nil {\n\t\t\treturn errors.New(\"storageSetting must be populated for key STORAGE\")\n\t\t}\n\t\t// Normalization would silently self-heal this misconfiguration to LOCAL;\n\t\t// a deployment file declaring S3 without a config should fail loudly.\n\t\tif storage.StorageType == storepb.InstanceStorageSetting_S3 && storage.S3Config == nil && len(storage.Storages) == 0 {\n\t\t\treturn errors.New(\"storageSetting.s3Config is required for S3\")\n\t\t}\n\t\tNormalizeInstanceStorageSetting(storage)\n\t\tif storage.UploadSizeLimitMb < 0 {\n\t\t\treturn errors.New(\"storageSetting.uploadSizeLimitMb must not be negative\")\n\t\t}\n\t\tdefaultStorage := GetDefaultStorage(storage)\n\t\tif defaultStorage != nil && defaultStorage.Type == storepb.StorageType_STORAGE_TYPE_S3 {\n\t\t\ts3Config := defaultStorage.GetS3Config()\n\t\t\tif s3Config == nil {\n\t\t\t\treturn errors.New(\"storageSetting default storage S3 config is required\")\n\t\t\t}\n\t\t\tfor _, field := range []struct {\n\t\t\t\tname  string","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/store/deployment_config.go#L216-L252","documentation":"Thrown when an instance-setting deployment file declares \"key\": \"STORAGE\" but the storageSetting payload message is absent (GetStorageSetting() == nil). The key/payload pair must be consistent; a STORAGE setting with no payload cannot express a storage type or upload limit, so the loader fails with 'invalid instance setting deployment file' at startup.","triggerScenarios":"A memos-instance-setting-storage.json containing only { \"key\": \"STORAGE\" }, or with a mistyped payload key (\"storage_setting\", \"storage\") that protojson ignores so the oneof stays unset.","commonSituations":"Authoring a storage file that only lists S3 storages at the wrong nesting level; templating that renders an empty object; renaming keys when converting from the admin API JSON dump.","solutions":["Add a \"storageSetting\" object: { \"key\": \"STORAGE\", \"storageSetting\": { \"storageType\": \"LOCAL\", \"uploadSizeLimitMb\": 32 } }.","Check the exact lowerCamelCase key storageSetting."],"exampleFix":"// before\n{ \"key\": \"STORAGE\" }\n\n// after\n{ \"key\": \"STORAGE\", \"storageSetting\": { \"storageType\": \"LOCAL\", \"uploadSizeLimitMb\": 32 } }","handlingStrategy":"validation","validationCode":"if setting.Key == storepb.InstanceSettingKey_STORAGE && setting.GetStorageSetting() == nil {\n    return errors.New(\"STORAGE setting requires a storageSetting payload\")\n}","typeGuard":"func hasStoragePayload(s *storepb.InstanceSetting) bool {\n    return s.GetKey() == storepb.InstanceSettingKey_STORAGE && s.GetStorageSetting() != nil\n}","tryCatchPattern":null,"preventionTips":["Never ship a key-only setting file; the payload is what the server applies.","Verify payload keys with the generated proto TypeScript/Go types rather than from memory."],"tags":["configuration","validation","instance-setting","storage","startup"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}