grafana/k6 · error

invalid reflectMetadata param: %w

Error message

invalid reflectMetadata param: %w

What it means

reflectMetadata in client.connect() params is parsed by the same newMetadata() used for call metadata: it must be a plain object of string values (plus Uint8Array/ArrayBuffer for -bin keys) that k6 attaches to reflection requests. Any other shape or value type is wrapped as 'invalid reflectMetadata param'.

Source

Thrown at internal/js/modules/k6/grpc/params.go:180

			if !ok {
				return result, fmt.Errorf("invalid plaintext value: '%#v', it needs to be boolean", v)
			}
		case "timeout":
			var err error
			result.Timeout, err = types.GetDurationValue(v)
			if err != nil {
				return result, fmt.Errorf("invalid timeout value: %w", err)
			}
		case "reflect":
			var ok bool
			result.UseReflectionProtocol, ok = v.(bool)
			if !ok {
				return result, fmt.Errorf("invalid reflect value: '%#v', it needs to be boolean", v)
			}
		case "reflectMetadata":
			md, err := newMetadata(params.Get(k))
			if err != nil {
				return result, fmt.Errorf("invalid reflectMetadata param: %w", err)
			}

			result.ReflectionMetadata = md
		case "maxReceiveSize":
			var ok bool
			result.MaxReceiveSize, ok = v.(int64)
			if !ok {
				return result, fmt.Errorf("invalid maxReceiveSize value: '%#v', it needs to be an integer", v)
			}
			if result.MaxReceiveSize < 0 {
				return result, fmt.Errorf("invalid maxReceiveSize value: '%#v, it needs to be a positive integer", v)
			}
		case "maxSendSize":
			var ok bool
			result.MaxSendSize, ok = v.(int64)
			if !ok {
				return result, fmt.Errorf("invalid maxSendSize value: '%#v', it needs to be an integer", v)
			}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Pass a plain object: reflectMetadata: { auth: 'token' }
  2. Apply the same rules as call metadata: strings for normal keys, Uint8Array for -bin keys
  3. Read the wrapped cause after the colon in the message to find the offending key

Example fix

// before
client.connect(addr, { reflect: true, reflectMetadata: 'auth=token' });

// after
client.connect(addr, { reflect: true, reflectMetadata: { auth: 'token' } });
Defensive patterns

Strategy: validation

Validate before calling

if (connectParams.reflectMetadata != null) {
  assertGrpcMetadata(connectParams.reflectMetadata, 'reflectMetadata');
}
client.connect(addr, connectParams);

Type guard

function isPlainObject(v) {
  return v != null && typeof v === 'object' && !Array.isArray(v);
}

Prevention

When it happens

Trigger: connect(addr, { reflect: true, reflectMetadata: 'auth=token' }) (string, not object); { reflectMetadata: { 'trace-bin': 'xyz' } }; { reflectMetadata: ['auth'] }.

Common situations: Passing grpcurl-style header strings; reusing header arrays from other clients; forgetting the string/binary value rules apply here too.

Related errors


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