grafana/k6 · error

unsupported type: %T

Error message

unsupported type: %T

What it means

While filling Blob data, parts that export to a Go map[string]any (i.e. JS objects) are only accepted when they are a DataView or a real Blob; every other object hits this 'unsupported type: map[string]interface {}' error, which is then rethrown as 'failed to process [blobParts]'.

Source

Thrown at internal/js/modules/k6/websockets/blob.go:130

			case []uint8:
				_, err = b.data.Write(v)
			case []int8, []int16, []int32, []int64, []uint16, []uint32, []uint64, []float32, []float64:
				err = binary.Write(b.data, binary.LittleEndian, v)
			case sobek.ArrayBuffer:
				_, err = b.data.Write(v.Bytes())
			case *sobek.ArrayBuffer:
				_, err = b.data.Write(v.Bytes())
			case string:
				_, err = b.data.WriteString(v)
			case map[string]any:
				obj := call.Arguments[0].ToObject(rt).Get(strconv.FormatInt(int64(n), 10)).ToObject(rt)
				switch {
				case isDataView(obj, rt):
					_, err = b.data.Write(obj.Get("buffer").Export().(sobek.ArrayBuffer).Bytes()) //nolint:forcetypeassert
				case isBlob(obj, r.blobConstructor):
					_, err = b.data.Write(extractBytes(obj, rt))
				default:
					err = fmt.Errorf("unsupported type: %T", part)
				}
			default:
				err = fmt.Errorf("unsupported type: %T", part)
			}
			if err != nil {
				common.Throw(rt, fmt.Errorf("failed to process [blobParts]: %w", err))
			}
		}
	}
}

func (r *WebSocketsAPI) slice(call sobek.FunctionCall, b *blob, rt *sobek.Runtime) sobek.Value {
	var (
		from int
		to   = b.data.Len()
		ct   = ""
	)

View on GitHub (pinned to 93accf6570)

Solutions

  1. Serialize objects first: new Blob([JSON.stringify(obj)])
  2. Only nest real Blob instances produced by the same ws.Blob constructor
  3. For binary object data, convert to ArrayBuffer or Uint8Array before constructing the Blob

Example fix

// before
const b = new ws.Blob([{ name: 'k6', v: 1 }]); // object part -> unsupported type

// after
const b = new ws.Blob([JSON.stringify({ name: 'k6', v: 1 })]);
Defensive patterns

Strategy: type-guard

Validate before calling

function safeParts(parts) {
  return parts.map(p => {
    if (typeof p === 'string' || p instanceof ArrayBuffer || ArrayBuffer.isView(p)) return p;
    if (p && typeof p === 'object' && !(p instanceof WS.Blob) && p.arrayBuffer === undefined) return JSON.stringify(p);
    return p;
  });
}
const b = new WS.Blob(safeParts(parts));

Type guard

const isSupportedBlobPart = (p, BlobCtor) =>
  typeof p === 'string' || p instanceof ArrayBuffer || ArrayBuffer.isView(p) || p instanceof BlobCtor;

Try / catch

try { b = new WS.Blob(parts); } catch (e) { if (/unsupported type: map/.test(e.message)) throw new Error('object in blobParts - JSON.stringify it first'); throw e; }

Prevention

When it happens

Trigger: new ws.Blob([{ foo: 'bar' }]) with a plain object element; passing a JSON-parsed value (JSON.parse returns objects/maps); passing an object that merely duck-types a Blob but was not created by the same Blob constructor (instanceof check via blobConstructor fails); class instances whose export is a map.

Common situations: Trying to serialize an object into a Blob directly instead of JSON.stringify-ing it; wrapping third-party 'blob-like' objects from another module; passing {buffer, byteOffset} literal structures expecting DataView semantics; copy-pasting browser code that relies on structured cloning k6 does not implement.

Related errors


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