{"record":{"id":"86a3ce0d9fc2d6e1","repo":"usememos/memos","slug":"failed-to-decode-protobuf-json-verify-field-names","errorCode":null,"errorMessage":"failed to decode protobuf JSON; verify field names, value types, and JSON syntax","messagePattern":"failed to decode protobuf JSON; verify field names, value types, and JSON syntax","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store/deployment_config.go","lineNumber":153,"sourceCode":"\tinfo, err = file.Stat()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to inspect file\")\n\t}\n\tif !info.Mode().IsRegular() {\n\t\treturn errors.New(\"file must resolve to a regular file\")\n\t}\n\tcontent, err := io.ReadAll(io.LimitReader(file, maxDeploymentConfigurationSize+1))\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to read file\")\n\t}\n\tif len(content) > maxDeploymentConfigurationSize {\n\t\treturn errors.Errorf(\"file exceeds %d bytes\", maxDeploymentConfigurationSize)\n\t}\n\tif err := (protojson.UnmarshalOptions{DiscardUnknown: false}).Unmarshal(content, message); err != nil {\n\t\tif matches := protoJSONUnknownFieldMatcher.FindStringSubmatch(err.Error()); len(matches) == 2 {\n\t\t\treturn errors.Errorf(\"failed to decode protobuf JSON: unknown field %q\", matches[1])\n\t\t}\n\t\treturn errors.New(\"failed to decode protobuf JSON; verify field names, value types, and JSON syntax\")\n\t}\n\treturn nil\n}\n\nfunc validateDeploymentIdentityProvider(provider *storepb.IdentityProvider) error {\n\tif provider.Id != 0 {\n\t\treturn errors.New(\"id must be omitted\")\n\t}\n\tif !base.UIDMatcher.MatchString(provider.Uid) {\n\t\treturn errors.New(\"uid is invalid\")\n\t}\n\tif strings.TrimSpace(provider.Name) == \"\" {\n\t\treturn errors.New(\"name is required\")\n\t}\n\tif provider.Type != storepb.IdentityProvider_OAUTH2 {\n\t\treturn errors.New(\"type must be OAUTH2\")\n\t}\n\tif provider.IdentifierFilter != \"\" {","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/store/deployment_config.go#L135-L171","documentation":"readDeploymentProtoJSON unmarshals the file with protojson using DiscardUnknown: false, so any JSON malformation, wrong field name casing, or wrong value type fails. When the underlying error is not a recognizable unknown-field error, it is replaced with the generic hint \"failed to decode protobuf JSON; verify field names, value types, and JSON syntax\", losing the original detail.","triggerScenarios":"A deployment JSON file with wrong proto field casing (camelCase vs snake_case mix-ups are tolerated by protojson, but typos are not), string where a number is expected, enum values not matching proto enum names, trailing commas, or a BOM.","commonSituations":"Hand-edited IdP bootstrap JSON; files written with UTF-8 BOM by Windows editors; field names taken from a different proto version; booleans passed as \"true\" strings.","solutions":["Validate the file with a JSON linter first (jsonschema/json tooling) to catch syntax errors","Match field names and value types exactly to the proto message (see proto/store definitions), including enum name spellings","Re-save without BOM; keep the file under maxDeploymentConfigurationSize","Reproduce with protojson.Unmarshal locally to get the underlying error message"],"exampleFix":"// before (memos-idp-x.json)\n{ \"name\": \"OAuth\", \"type\": 1, \"config\": { \"oauth2\": { \"clientId\": \"abc\", \"authUrl\": \"https://sso/auth\" } } }\n// after — use enum names and check exact field names against the proto\n{ \"uid\": \"github-oauth\", \"name\": \"OAuth\", \"type\": \"OAUTH2\", \"config\": { \"oauth2\": { \"clientId\": \"abc\", \"authUrl\": \"https://sso/auth\" } } }","handlingStrategy":"validation","validationCode":"data, _ := os.ReadFile(path)\nif !json.Valid(data) {\n    return fmt.Errorf(\"deployment config is not valid JSON\")\n}\nif err := protojson.UnmarshalOptions{DiscardUnknown: false}.Unmarshal(data, msg); err != nil {\n    return fmt.Errorf(\"proto decode failed: %w\", err) // keep the detailed error\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate deployment JSON with json.Valid and a linter before startup","Cross-check field names, enum spellings, and types against the proto definitions","Save config files without a UTF-8 BOM"],"tags":["deployment","configuration","protobuf","json","validation"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}