grafana/k6 · error
unknown param: %q
Error message
unknown param: %q
What it means
newCallParams accepts exactly four keys: metadata, tags, timeout, discardResponseMessage. The switch's default branch rejects every other property in the params object passed to client.invoke() or new grpc.Stream(), so a single unknown or misspelled key fails the whole call with "unknown param".
Source
Thrown at internal/js/modules/k6/grpc/params.go:65
return result, fmt.Errorf("invalid metadata param: %w", err)
}
result.Metadata = md
case "tags":
if err := common.ApplyCustomUserTags(rt, &result.TagsAndMeta, params.Get(k)); err != nil {
return result, fmt.Errorf("metric tags: %w", err)
}
case "timeout":
var err error
v := params.Get(k).Export()
result.Timeout, err = types.GetDurationValue(v)
if err != nil {
return result, fmt.Errorf("invalid timeout value: %w", err)
}
case "discardResponseMessage":
result.DiscardResponseMessage = params.Get(k).ToBoolean()
default:
return result, fmt.Errorf("unknown param: %q", k)
}
}
return result, nil
}
// newMetadata constructs a metadata.MD from the input value.
func newMetadata(input sobek.Value) (metadata.MD, error) {
md := metadata.New(nil)
if common.IsNullish(input) {
return md, nil
}
v := input.Export()
rawHeaders, ok := v.(map[string]any)
if !ok {View on GitHub (pinned to 93accf6570)
Solutions
- Rename headers to metadata
- Remove unsupported keys; set the metric name via tags: { name: 'checkout' }
- Whitelist-validate the params object before passing it (see defense)
Example fix
// before
client.invoke(method, req, { headers: { 'x-tag': 'v' }, name: 'checkout' });
// after
client.invoke(method, req, { metadata: { 'x-tag': 'v' }, tags: { name: 'checkout' } }); Defensive patterns
Strategy: validation
Validate before calling
const CALL_PARAM_KEYS = new Set(['metadata', 'tags', 'timeout', 'discardResponseMessage']);
function hasOnlyKnownCallParams(p) {
return p == null || Object.keys(p).every((k) => CALL_PARAM_KEYS.has(k));
}
if (!hasOnlyKnownCallParams(params)) {
const bad = Object.keys(params).filter((k) => !CALL_PARAM_KEYS.has(k));
throw new Error(`unknown grpc call params: ${bad.join(', ')}`);
} Type guard
function isCallParamsObject(p) {
if (p == null) return true;
const allowed = new Set(['metadata', 'tags', 'timeout', 'discardResponseMessage']);
return Object.keys(p).every((k) => allowed.has(k));
} Prevention
- Remember grpc uses metadata, not headers
- Set metric names via tags: { name: '...' }, not a top-level name key
- Keep separate param builders for http and grpc instead of one shared object
When it happens
Trigger: { headers: {...} } (HTTP-style naming); { discardResponseMessages: true } (plural typo); { name: 'checkout' } (not a grpc call param); { auth: 'token' }.
Common situations: k6/http users reusing options objects for grpc calls; shared param helpers; key lists drifting between k6 versions or between modules.
Related errors
- invalid GRPC Stream's parameters: %w
- method to invoke cannot be empty
- request cannot be nil
- empty gRPC client
- no gRPC connection, you must call connect first
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/657c854159db2252.
Report an issue: GitHub.