grafana/k6 · error
cannot add tags for the '%s' custom metric: %w
Error message
cannot add tags for the '%s' custom metric: %w
What it means
Thrown by k6 custom metrics when the optional tags argument to .add(value, tags) cannot be applied. After the value passes validation, Metric.add (internal/js/modules/k6/metrics/metrics.go:113-116) calls common.ApplyCustomUserTags with the tags argument; if it is not a plain object of string keys/values (e.g. a string, number, or array), the wrapped error is returned unconditionally — unlike value errors, this always errors regardless of the throw option.
Source
Thrown at internal/js/modules/k6/metrics/metrics.go:115
return raiseErr(fmt.Errorf("no value was provided for metric '%s', a number or a boolean value is expected",
m.metric.Name))
}
if sobek.IsNull(v) {
return raiseNan()
}
vfloat := v.ToFloat()
if vfloat == 0 && v.ToBoolean() {
vfloat = 1.0
}
if math.IsNaN(vfloat) {
return raiseNan()
}
ctm := state.Tags.GetCurrentValues()
if err := common.ApplyCustomUserTags(m.vu.Runtime(), &ctm, addTags); err != nil {
return false, fmt.Errorf("cannot add tags for the '%s' custom metric: %w", m.metric.Name, err)
}
sample := metrics.Sample{
TimeSeries: metrics.TimeSeries{
Metric: m.metric,
Tags: ctm.Tags,
},
Time: time.Now(),
Metadata: ctm.Metadata,
Value: vfloat,
}
metrics.PushIfNotDone(m.vu.Context(), state.Samples, sample)
return true, nil
}
type (
// RootModule is the root metrics module
RootModule struct{}View on GitHub (pinned to 93accf6570)
Solutions
- Wrap tags in an object with string values: myCounter.add(1, { code: String(resp.status) }).
- Check argument order — the signature is add(value, tags), not add(tags, value).
- Omit the second argument entirely if no tags are needed: myCounter.add(1).
- Coerce non-string values (numbers, booleans) inside the tags object to strings.
Example fix
// before
myCounter.add(resp.status); // value ok, but intended as tag
myTrend.add(5, resp.status); // tags = number -> error
// after
myTrend.add(5, { code: String(resp.status) }); Defensive patterns
Strategy: validation
Validate before calling
function safeAdd(metric, value, tags) {
let t = tags;
if (t !== undefined && t !== null) {
if (typeof t !== 'object' || Array.isArray(t)) throw new Error('tags must be an object of string keys/values');
t = Object.fromEntries(Object.entries(t).map(([k, v]) => [k, String(v)]));
}
metric.add(value, t);
} Type guard
const isTagsObject = (t) => t == null || (typeof t === 'object' && !Array.isArray(t) && Object.values(t).every((v) => typeof v === 'string'));
Prevention
- Keep the argument order add(value, tags) in mind; never pass primitives as tags.
- Stringify numeric tag values (status codes, timings) at the call site.
When it happens
Trigger: myCounter.add(1, 'error'); myTrend.add(5, 200); myGauge.add(3, ['a','b']); myRate.add(1, null-as-object). Passing a serialized JSON string instead of an object also fails the map conversion.
Common situations: Passing a status code number or a tag string directly instead of an object; reusing a response header string as tags; a helper signature mismatch where tags and value are swapped (add(tags, value)).
Related errors
- '%s' is an invalid value for metric '%s', a number or a bool
- no value was provided for metric '%s', a number or a boolean
- invalid tag, empty name
- invalid tag, empty value
- invalid metric type
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/ace6d626207adc97.
Report an issue: GitHub.