{"record":{"id":"045175513824231b","repo":"grafana/k6","slug":"unable-to-serialise-request-object-w","errorCode":null,"errorMessage":"unable to serialise request object: %w","messagePattern":"unable to serialise request object: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/client.go","lineNumber":393,"sourceCode":"\tif p.Timeout == time.Duration(0) {\n\t\tp.Timeout = 2 * time.Minute\n\t}\n\n\tif req == nil {\n\t\treturn grpcReq, errors.New(\"request cannot be nil\")\n\t}\n\n\tobject := req.ToObject(c.vu.Runtime())\n\n\tvar stack []*sobek.Object\n\tnormalized, err := normalizeNumberStrings(object, c.vu.Runtime(), stack)\n\tif err != nil {\n\t\treturn grpcReq, fmt.Errorf(\"unable to normalize number strings: %w\", err)\n\t}\n\n\tb, err := normalized.ToObject(c.vu.Runtime()).MarshalJSON()\n\tif err != nil {\n\t\treturn grpcReq, fmt.Errorf(\"unable to serialise request object: %w\", err)\n\t}\n\n\tp.SetSystemTags(state, c.addr, method)\n\n\treturn grpcext.InvokeRequest{\n\t\tMethod:                 method,\n\t\tMethodDescriptor:       methodDesc,\n\t\tTimeout:                p.Timeout,\n\t\tDiscardResponseMessage: p.DiscardResponseMessage,\n\t\tMessage:                b,\n\t\tTagsAndMeta:            &p.TagsAndMeta,\n\t\tMetadata:               p.Metadata,\n\t}, nil\n}\n\n// normalizeNumberStrings recursively traverses a sobek.Value. It creates a deep copy of any\n// objects or arrays, and converts special float values (NaN, Infinity) to their\n// string representations for proper JSON serialization.","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/grpc/client.go#L375-L411","documentation":"After normalization, the request object is marshaled with MarshalJSON; values JSON cannot represent (functions, Symbols, BigInts) or a throwing toJSON getter make marshaling fail, wrapped as 'unable to serialise request object' (internal/js/modules/k6/grpc/client.go:393). Unlike the normalize step, this is about value types, not reference cycles.","triggerScenarios":"client.invoke(m, { id: 10n }) with a BigInt; passing a function or Symbol as a field; objects whose custom toJSON/getter throws during serialization.","commonSituations":"IDs computed as BigInt to avoid precision loss; accidentally including a function, logger, or SDK client in the payload; subclassed objects with exotic accessors.","solutions":["Convert BigInts to Number or String before invoking","Strip functions and non-data fields; pass a plain data object built specifically for the message","Pre-serialize once with JSON.stringify(req) in the script to get a precise early error with a stack trace"],"exampleFix":"// before\nclient.invoke('/svc/Set', { userId: 9007199254740993n });\n\n// after\nclient.invoke('/svc/Set', { userId: '9007199254740993' }); // string keeps precision","handlingStrategy":"validation","validationCode":"// fails on BigInt/functions with a precise JS stack trace before invoke()\nfunction assertSerializable(req) {\n  try { JSON.stringify(req); }\n  catch (e) { throw new Error(`request not JSON-serializable: ${e.message}`); }\n  return req;\n}\nclient.invoke(method, assertSerializable(req));","typeGuard":"function isJsonSafe(v) {\n  if (typeof v === 'bigint' || typeof v === 'function' || typeof v === 'symbol') return false;\n  if (v === null || typeof v !== 'object') return true;\n  return Object.values(v).every(isJsonSafe);\n}","tryCatchPattern":"try { client.invoke(m, req); } catch (e) { if (/unable to serialise request object/.test(e.message)) { /* convert BigInts, strip functions, retry */ } throw e; }","preventionTips":["Convert BigInt IDs to strings or Numbers before invoke","Pass plain data objects, not objects carrying methods or SDK handles","Pre-check with JSON.stringify in dev builds of the script"],"tags":["grpc","k6","json","serialization","bigint"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}