{"record":{"id":"53c34d05e4059dbd","repo":"grafana/k6","slug":"unknown-grpc-stream-s-event-type-s","errorCode":null,"errorMessage":"unknown GRPC stream's event type: %s","messagePattern":"unknown GRPC stream's event type: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/listeners.go","lineNumber":66,"sourceCode":"\tcase eventData:\n\t\treturn l.data\n\tcase eventError:\n\t\treturn l.error\n\tcase eventStatus:\n\t\treturn l.status\n\tcase eventEnd:\n\t\treturn l.end\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// add adds a listener to the listeners\nfunc (l *eventListeners) add(t string, f func(sobek.Value, sobek.Value) (sobek.Value, error)) error {\n\tlist := l.getType(t)\n\n\tif list == nil {\n\t\treturn fmt.Errorf(\"unknown GRPC stream's event type: %s\", t)\n\t}\n\n\tlist.add(f)\n\n\treturn nil\n}\n\n// all returns all possible listeners for a certain event type or an empty array\nfunc (l *eventListeners) all(t string) []func(sobek.Value, sobek.Value) (sobek.Value, error) {\n\tlist := l.getType(t)\n\n\tif list == nil {\n\t\treturn []func(sobek.Value, sobek.Value) (sobek.Value, error){}\n\t}\n\n\treturn list.list\n}\n","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/grpc/listeners.go#L48-L84","documentation":"stream.on(eventType, callback) accepts only the event types defined in listeners.go: 'data', 'error', 'end' and 'status'. eventListeners.add() looks the name up via getType(); anything else returns nil and the API throws \"unknown GRPC stream's event type\".","triggerScenarios":"stream.on('message', cb) (Node.js/EventEmitter habit; k6 uses 'data'); stream.on('close', cb) (not supported); capitalization typos like 'Data' or 'End'.","commonSituations":"Scripts ported from Node stream/socket code; authors expecting naming symmetric with grpcurl or browser EventSource; auto-completed wrong event names.","solutions":["Use 'data' for received messages","Use 'error' for stream errors and 'end' for stream completion","Use 'status' for status updates if needed; there is no 'message' or 'close' event"],"exampleFix":"// before\nstream.on('message', (m) => console.log(m));\nstream.on('close', () => console.log('done'));\n\n// after\nstream.on('data', (m) => console.log(m));\nstream.on('end', () => console.log('done'));","handlingStrategy":"validation","validationCode":"const STREAM_EVENTS = new Set(['data', 'error', 'end', 'status']);\nfunction safeOn(stream, event, fn) {\n  if (!STREAM_EVENTS.has(event)) {\n    throw new Error(`unsupported stream event '${event}'; expected one of: ${[...STREAM_EVENTS].join(', ')}`);\n  }\n  return stream.on(event, fn);\n}\nsafeOn(stream, 'data', (m) => console.log(m));","typeGuard":"function isStreamEvent(e) {\n  return e === 'data' || e === 'error' || e === 'end' || e === 'status';\n}","tryCatchPattern":null,"preventionTips":["Remember the mapping: Node 'message' -> k6 'data'; there is no 'close' event","Register 'error' on every stream so failures surface instead of halting the VU silently","Keep event names in constants instead of inline strings"],"tags":["grpc","stream","events","api-misuse"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}