grafana/k6 · error

%q value must be a string

Error message

%q value must be a string

What it means

Metadata keys that do not end in -bin must map to string values; newMetadata asserts the exported JS value is a Go string (params.go:99). Numbers, booleans, objects, arrays or null on a normal key throw '%q value must be a string'.

Source

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

	rawHeaders, ok := v.(map[string]any)
	if !ok {
		return md, errors.New("must be an object with key-value pairs")
	}

	for hk, kv := range rawHeaders {
		var val string
		// The gRPC spec defines that Binary-valued keys end in -bin
		// https://grpc.io/docs/what-is-grpc/core-concepts/#metadata
		if strings.HasSuffix(hk, "-bin") {
			var binVal []byte
			if binVal, ok = kv.([]byte); !ok {
				return md, fmt.Errorf("%q value must be binary", hk)
			}

			// https://github.com/grpc/grpc-go/blob/v1.57.0/Documentation/grpc-metadata.md#storing-binary-data-in-metadata
			val = string(binVal)
		} else if val, ok = kv.(string); !ok {
			return md, fmt.Errorf("%q value must be a string", hk)
		}

		md.Append(hk, val)
	}

	return md, nil
}

// SetSystemTags sets the system tags for the call.
func (p *callParams) SetSystemTags(state *lib.State, addr string, methodName string) {
	if state.Options.SystemTags.Has(metrics.TagURL) {
		p.TagsAndMeta.SetSystemTagOrMeta(metrics.TagURL, fmt.Sprintf("%s%s", addr, methodName))
	}

	parts := strings.Split(methodName[1:], "/")
	p.TagsAndMeta.SetSystemTagOrMetaIfEnabled(state.Options.SystemTags, metrics.TagService, parts[0])
	p.TagsAndMeta.SetSystemTagOrMetaIfEnabled(state.Options.SystemTags, metrics.TagMethod, parts[1])

View on GitHub (pinned to 93accf6570)

Solutions

  1. Stringify scalars: String(42), String(true)
  2. For genuinely binary data, rename the key with a -bin suffix and pass a Uint8Array

Example fix

// before
{ metadata: { 'x-user-id': 42 } }

// after
{ metadata: { 'x-user-id': '42' } }
Defensive patterns

Strategy: type-guard

Validate before calling

for (const [k, v] of Object.entries(params.metadata || {})) {
  if (!k.endsWith('-bin') && typeof v !== 'string') {
    throw new Error(`metadata['${k}'] must be a string, got ${typeof v}`);
  }
}
client.invoke(method, req, params);

Type guard

function isStringMetadataValue(key, v) {
  return key.endsWith('-bin') ? v instanceof Uint8Array : typeof v === 'string';
}

Prevention

When it happens

Trigger: { 'x-user-id': 42 }; { active: true }; { user: { id: 1 } }; { ref: null }.

Common situations: Sending numeric IDs or flags as metadata without stringifying; spreading parsed JSON directly into metadata objects.

Related errors


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