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

  1. Rename headers to metadata
  2. Remove unsupported keys; set the metric name via tags: { name: 'checkout' }
  3. 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

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


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/657c854159db2252. Report an issue: GitHub.