grafana/k6 · error

invalid GRPC Stream's parameters: %w

Error message

invalid GRPC Stream's parameters: %w

What it means

The optional third argument of new grpc.Stream(client, method, params) is validated by newCallParams(), which accepts only four keys: metadata, tags, timeout and discardResponseMessage. Any failure inside that validation (bad metadata object, non-scalar tag value, unparseable timeout, unknown key) is wrapped and rethrown as "invalid GRPC Stream's parameters".

Source

Thrown at internal/js/modules/k6/grpc/grpc.go:128

// stream returns a new stream object
func (mi *ModuleInstance) stream(c sobek.ConstructorCall) *sobek.Object {
	rt := mi.vu.Runtime()

	client, err := extractClient(c.Argument(0), rt)
	if err != nil {
		common.Throw(rt, fmt.Errorf("invalid GRPC Stream's client: %w", err))
	}

	methodName := sanitizeMethodName(c.Argument(1).String())
	methodDescriptor, err := client.getMethodDescriptor(methodName)
	if err != nil {
		common.Throw(rt, fmt.Errorf("invalid GRPC Stream's method: %w", err))
	}

	p, err := newCallParams(mi.vu, c.Argument(2))
	if err != nil {
		common.Throw(rt, fmt.Errorf("invalid GRPC Stream's parameters: %w", err))
	}

	p.SetSystemTags(mi.vu.State(), client.addr, methodName)

	logger := mi.vu.State().Logger.WithField("streamMethod", methodName)

	s := &stream{
		vu:               mi.vu,
		client:           client,
		methodDescriptor: methodDescriptor,
		method:           methodName,
		logger:           logger,

		tq: taskqueue.New(mi.vu.RegisterCallback),

		instanceMetrics: mi.metrics,
		builtinMetrics:  mi.vu.State().BuiltinMetrics,
		done:            make(chan struct{}),

View on GitHub (pinned to 93accf6570)

Solutions

  1. Read the wrapped cause after the colon in the message; it names the exact offending key and expected type
  2. Keep only metadata, tags, timeout and discardResponseMessage in the object
  3. Validate the params object with a helper before passing it (see defense)

Example fix

// before
const stream = new grpc.Stream(client, METHOD, { headers: { 'x-tag': 'v' } });

// after
const stream = new grpc.Stream(client, METHOD, { metadata: { 'x-tag': 'v' } });
Defensive patterns

Strategy: validation

Validate before calling

const CALL_PARAM_KEYS = new Set(['metadata', 'tags', 'timeout', 'discardResponseMessage']);
function assertCallParams(p) {
  if (p == null) return;
  for (const k of Object.keys(p)) {
    if (!CALL_PARAM_KEYS.has(k)) throw new Error(`unknown grpc param '${k}'`);
  }
  if (p.timeout != null && !isDurationValue(p.timeout)) throw new Error('invalid timeout');
  if (p.metadata != null) assertGrpcMetadata(p.metadata);
}
assertCallParams(params);
const stream = new grpc.Stream(client, METHOD, params);

Prevention

When it happens

Trigger: new grpc.Stream(client, method, { headers: {...} }) (unknown key); { metadata: { 'x-bin': 'text' } } (binary key with a string value); { timeout: 'soon' }; { tags: { user: {} } }.

Common situations: Reusing a params object built for client.invoke() that carries extra keys; sharing an HTTP-flavoured options helper across protocols; key names drifting between k6 versions.

Related errors


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