{"record":{"id":"9a3709bdb98a7adc","repo":"go-kratos/kratos","slug":"no-value-provided","errorCode":null,"errorMessage":"no value provided","messagePattern":"no value provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"info","filePath":"encoding/form/proto_decode.go","lineNumber":42,"sourceCode":"\nvar errInvalidFormatMapKey = errors.New(\"invalid formatting for map key\")\n\n// DecodeValues decode url value into proto message.\nfunc DecodeValues(msg proto.Message, values url.Values) error {\n\tfor key, values := range values {\n\t\tif err := populateFieldValues(msg.ProtoReflect(), strings.Split(key, \".\"), values); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc populateFieldValues(v protoreflect.Message, fieldPath []string, values []string) error {\n\tif len(fieldPath) < 1 {\n\t\treturn errors.New(\"no field path\")\n\t}\n\tif len(values) < 1 {\n\t\treturn errors.New(\"no value provided\")\n\t}\n\n\tvar fd protoreflect.FieldDescriptor\n\tfor i, fieldName := range fieldPath {\n\t\tif fd = getFieldDescriptor(v, fieldName); fd == nil {\n\t\t\t// ignore unexpected field.\n\t\t\treturn nil\n\t\t}\n\t\tif fd.IsMap() && len(fieldPath) == 2 {\n\t\t\treturn populateMapField(fd, v.Mutable(fd).Map(), fieldPath, values)\n\t\t}\n\t\tif i == len(fieldPath)-1 {\n\t\t\tbreak\n\t\t}\n\t\tif fd.Message() == nil || fd.Cardinality() == protoreflect.Repeated {\n\t\t\tif fd.IsMap() && len(fieldPath) > 1 {\n\t\t\t\t// post subfield\n\t\t\t\treturn populateMapField(fd, v.Mutable(fd).Map(), []string{fieldPath[1]}, values)","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/go-kratos/kratos/blob/668db92c2c001e9552594ba5a8aede8456af6d7e/encoding/form/proto_decode.go#L24-L60","documentation":"'no value provided' (encoding/form/proto_decode.go:42) is the second defensive guard in populateFieldValues: it fires when the values slice is empty. url.Values (the only input to the public DecodeValues) maps every key to a slice with at least one element - even 'a=' yields [\"\"] - so through the supported API this cannot trigger. As with the field-path guard, it exists to protect internal invariants for direct callers of the unexported helper (forks, tests, refactors).","triggerScenarios":"Internal/direct calls of populateFieldValues(msg, path, []string{}) or nil values; a modified copy of the codec where a caller filters out empty strings before passing values; reflect-based test harnesses reaching into the package.","commonSituations":"Locally forked or rewritten form codec; a refactor that pre-cleans values (e.g. dropping empties) introducing a zero-length slice; copying test cases from proto_decode_test.go that exercise internals directly.","solutions":["If you maintain a fork, guarantee at least one value string per field path before invoking the helper","In public usage, report it upstream with the exact url.Values that triggered it - it indicates a package bug","Avoid pre-filtering values slices to empty; keep the original 'a=' empty-string entry"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// guard any local preprocessing before calling the codec\nif len(vals) == 0 {\n    return fmt.Errorf(\"no values for key %q\", key)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass url.Values through unmodified - it always carries >=1 value per key","Never filter values slices to empty during pre-cleaning; keep empty-string entries","Treat encountering this error in production as an upstream bug to report with the input"],"tags":["encoding","form","proto","internal","defensive-check"],"backgroundTag":null,"analyzedSha":"668db92c2c001e9552594ba5a8aede8456af6d7e","analyzedAt":"2026-08-16T02:07:20.704Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}