grafana/k6 · error

invalid grpc.connect() parameters: %w

Error message

invalid grpc.connect() parameters: %w

What it means

grpc.connect() validates its params object with newConnectParams; any failure is wrapped as 'invalid grpc.connect() parameters: <cause>' (internal/js/modules/k6/grpc/client.go:227). The cause names the exact problem: 'unknown connect param: <key>' (typo or unsupported key), non-boolean plaintext/reflect, invalid timeout (needs a duration string like '10s' or a millisecond number), non-integer or negative maxReceiveSize/maxSendSize, non-string authority, invalid reflectMetadata, or a malformed tls object (expected keys cert, key, password, cacerts).

Source

Thrown at internal/js/modules/k6/grpc/client.go:227

				}
			}
		} else if caCertStr, caCertStrOk := cas.(string); caCertStrOk {
			ca = [][]byte{[]byte(caCertStr)}
		}
	}
	return buildTLSConfig(parentConfig, cert, key, ca)
}

// Connect is a block dial to the gRPC server at the given address (host:port)
func (c *Client) Connect(addr string, params sobek.Value) (bool, error) {
	state := c.vu.State()
	if state == nil {
		return false, common.NewInitContextError("connecting to a gRPC server in the init context is not supported")
	}

	p, err := newConnectParams(c.vu, params)
	if err != nil {
		return false, fmt.Errorf("invalid grpc.connect() parameters: %w", err)
	}

	opts := grpcext.DefaultOptions(c.vu.State)

	var tcred credentials.TransportCredentials
	if !p.IsPlaintext {
		tlsCfg := state.TLSConfig.Clone()
		if len(p.TLS) > 0 {
			if tlsCfg, err = buildTLSConfigFromMap(tlsCfg, p.TLS); err != nil {
				return false, err
			}
		}
		tlsCfg.NextProtos = []string{"h2"}

		tcred = credentials.NewTLS(tlsCfg)
	} else {
		tcred = insecure.NewCredentials()
	}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Read the wrapped cause after the colon - it names the offending key and the expected type
  2. Use only the documented keys: plaintext, timeout, reflect, reflectMetadata, maxReceiveSize, maxSendSize, tls, authority
  3. Set sizes as plain integer bytes and timeout as '600ms' / '10s' style strings

Example fix

// before
connect(addr, { maxReceiveSize: '4MB', plaintext: 'true' });

// after
connect(addr, { maxReceiveSize: 4 * 1024 * 1024, plaintext: true });
Defensive patterns

Strategy: validation

Validate before calling

const CONNECT_KEYS = new Set(['plaintext','timeout','reflect','reflectMetadata','maxReceiveSize','maxSendSize','tls','authority']);
function assertConnectParams(p) {
  for (const k of Object.keys(p)) {
    if (!CONNECT_KEYS.has(k)) throw new Error(`unknown connect param: ${k}`);
  }
  if (p.plaintext !== undefined && typeof p.plaintext !== 'boolean') throw new Error('plaintext must be boolean');
  if (p.maxReceiveSize !== undefined && (!Number.isInteger(p.maxReceiveSize) || p.maxReceiveSize < 0)) throw new Error('maxReceiveSize must be a non-negative integer');
  if (p.maxSendSize !== undefined && (!Number.isInteger(p.maxSendSize) || p.maxSendSize < 0)) throw new Error('maxSendSize must be a non-negative integer');
  if (p.authority !== undefined && typeof p.authority !== 'string') throw new Error('authority must be a string');
  return p;
}
client.connect(addr, assertConnectParams(params));

Try / catch

try { client.connect(addr, params); } catch (e) { if (/invalid grpc.connect\(\) parameters/.test(e.message)) { /* e.message's wrapped cause names the bad key; fix params and retry */ } throw e; }

Prevention

When it happens

Trigger: connect(addr, { plaintext: 'true' }); connect(addr, { timeOut: 1000 }) (typo -> unknown param); connect(addr, { maxReceiveSize: '4MB' }) (string instead of integer bytes); connect(addr, { tls: 'cert.pem' }) (string instead of object).

Common situations: Copy-pasting option styles from the HTTP module (expecting '4MB' size strings); renames/additions between k6 versions; long param objects with typos that silently become 'unknown param'.

Related errors


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