{"record":{"id":"1ce66b58e21a3e96","repo":"cilium/cilium","slug":"unexpected-rhs-expression-length","errorCode":null,"errorMessage":"unexpected RHS expression length","messagePattern":"unexpected RHS expression length","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"tools/metricslint/pkg/analyzer/analyzer.go","lineNumber":54,"sourceCode":"func getEllipsisRHSExpansion(expr ast.Expr) (*ast.CompositeLit, error) {\n\tvar ident *ast.Ident\n\n\tsel, ok := expr.(*ast.SelectorExpr)\n\tif ok {\n\t\tident, ok = sel.X.(*ast.Ident)\n\t} else {\n\t\tident, ok = expr.(*ast.Ident)\n\t}\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"unknown identifier\")\n\t}\n\n\tinlineAssignment, ok := ident.Obj.Decl.(*ast.AssignStmt)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"expected assignment statement\")\n\t}\n\tif len(inlineAssignment.Rhs) != 1 {\n\t\treturn nil, fmt.Errorf(\"unexpected RHS expression length\")\n\t}\n\n\tslice, ok := inlineAssignment.Rhs[0].(*ast.CompositeLit)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"expected composite literal\")\n\t}\n\treturn slice, nil\n}\n\nfunc countArgs(call *ast.CallExpr) (int, error) {\n\tif call.Ellipsis == token.NoPos {\n\t\t// Simple path: Args are directly specified to the method.\n\t\treturn len(call.Args), nil\n\t}\n\tif len(call.Args) != 1 {\n\t\treturn 0, fmt.Errorf(\"unsupported ellipsis expression\")\n\t}\n\tif warnDeprecated {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/tools/metricslint/pkg/analyzer/analyzer.go#L36-L72","documentation":"getEllipsisRHSExpansion requires the identifier's assigning statement to have exactly one RHS expression (i.e. a plain `x := expr`). Multi-value or tuple assignments such as `a, b := f()` have len(Rhs) != 1, so this error is returned. The analyzer cannot unambiguously attribute which RHS produced the spread slice.","triggerScenarios":"Spread argument was declared in a multi-value assignment, e.g. `keys, vals := splitLabels()` then `c.WithLabels(keys...)`; also `sl, err := build()` followed by `WithLabels(sl...)`.","commonSituations":"Metric labels derived from a function returning two values; comma-ok type assertions (`v, ok := m[\"k\"]`) used to build the slice.","solutions":["Split the declaration so the slice gets its own single-value assignment: `vals := getVals()` rather than destructuring a multi-return.","Reassign into a fresh single-value variable before the variadic call: `ks := keys; c.WithLabels(ks...)` still fails — instead build via `ks := []string{...}`.","Suppress/ignore the analyzer report if the code is valid Go.","Improve the tool to use go/types so tuple assignments resolve correctly."],"exampleFix":"// before\n// keys, extra := parseLabels(cfg)\n// counter.WithLabels(keys...)\n// after\n// all := parseLabels(cfg)\n// keys := all.keys\n// counter.WithLabels(keys...)","handlingStrategy":"validation","validationCode":"// Give the spread slice a single-RHS declaration:\n// BAD: keys, extra := parseLabels(cfg)\n// GOOD:\n// parsed := parseLabels(cfg)\n// keys := parsed.keys\nfunc hasSingleRHS(as *ast.AssignStmt) bool { return len(as.Rhs) == 1 }","typeGuard":"func isSingleValueAssign(ident *ast.Ident) bool {\n    as, ok := ident.Obj.Decl.(*ast.AssignStmt)\n    return ok && len(as.Rhs) == 1 && len(as.Lhs) == 1\n}","tryCatchPattern":"count, err := countArgs(call)\nif err != nil && strings.Contains(err.Error(), \"unexpected RHS expression length\") {\n    log.Printf(\"multi-value assignment not supported by metricslint; skipping\")\n    return\n}","preventionTips":["Avoid destructuring multi-return functions into the variable later spread with '...'.","Extract the slice into its own single-value assignment before the variadic call.","Keep tuple-assignment results out of metric With* call sites.","Review refactors that convert single := declarations into comma-ok or multi-return forms."],"tags":["go","static-analysis","ast","linter"],"backgroundTag":"analyzer-ast-parse-limitation","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}