cilium/cilium · info
expected Value as CallExpr
Error message
expected Value as CallExpr
What it means
The KeyValueExpr's value is not a function call (*ast.CallExpr). The analyzer only tracks initializer fields whose value directly calls a *Vec constructor, so non-call values (literals, identifiers, selector expressions) are rejected with this sentinel and skipped.
Source
Thrown at tools/metricslint/pkg/analyzer/analyzer.go:115
return 0, fmt.Errorf("unsupported nested varlen array: %w", err)
}
return len(nestedSlice.Elts), nil
}
func filterRelevantConstructors(node ast.Node) (object, constructor string, argCount int, err error) {
// Look for an initializer with key-value expressions that call another
// function to initialize the field.
kv, ok := node.(*ast.KeyValueExpr)
if !ok {
return "", "", 0, fmt.Errorf("expected KeyValueExpr")
}
key, ok := kv.Key.(*ast.Ident)
if !ok {
return "", "", 0, fmt.Errorf("expected Key as Ident")
}
call, ok := kv.Value.(*ast.CallExpr)
if !ok {
return "", "", 0, fmt.Errorf("expected Value as CallExpr")
}
// Look for a function with at least two args, where the last arg is a
// composite literal (such as a slice). Example:
//
// metric.NewCounterVec(opts, []string{...})
if len(call.Args) < 2 {
return "", "", 0, fmt.Errorf("expected 2+ arguments to constructor")
}
lastArg, ok := call.Args[len(call.Args)-1].(*ast.CompositeLit)
if !ok {
return "", "", 0, fmt.Errorf("expected last arg as CompositeLit")
}
// Store the object and the initializer function. Assume there's just
// one which has a composite literal as the last parameter.
object = key.Name
argCount = len(lastArg.Elts)View on GitHub (pinned to ac7b90affa)
Solutions
- No action needed — this is an expected skip for non-constructor initializers
- If the field is a metric, call the Vec constructor inline in the initializer rather than assigning a pre-built variable
Example fix
// before
var c = metric.NewCounterVec(opts, labels)
s := structA{counter: c}
// after
s := structA{counter: metric.NewCounterVec(opts, labels)} Defensive patterns
Strategy: type-guard
Type guard
call, ok := kv.Value.(*ast.CallExpr)
if !ok {
return // value is not a constructor call; skipped
} Prevention
- Call the Vec constructor inline in the field initializer
- Avoid assigning pre-built metrics variables in initializers you want linted
When it happens
Trigger: Struct fields initialized with plain values: counter: someVar, counter: pkg.PreexistingCounter, or counter: &struct{}{...} inside a composite literal scanned by metricslint.
Common situations: Assigning pre-built metrics from other packages or variables; initializing non-metric fields of the same struct; wrapping constructors in helper closures.
Related errors
- unknown identifier
- expected assignment statement
- unexpected RHS expression length
- expected composite literal
- unsupported ellipsis expression
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/05a4e4ee3daa1ada.
Report an issue: GitHub.