{"record":{"id":"8369a5cc50fcc451","repo":"grafana/k6","slug":"invalidaccesserror-failed-to-execute-close-on","errorCode":null,"errorMessage":"InvalidAccessError: Failed to execute 'close' on 'WebSocket': The close code must be either 1000, or between 3000 and 4999. %d is neither","messagePattern":"InvalidAccessError: Failed to execute 'close' on 'WebSocket': The close code must be either 1000, or between 3000 and 4999\\. (.+?) is neither","errorType":"exception","errorClass":"InvalidAccessError","httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/websockets/websockets.go","lineNumber":798,"sourceCode":"\t// TODO figure out if we should give different error while being closed/closed/connecting\n\tcommon.Throw(w.vu.Runtime(), errors.New(\"InvalidStateError\"))\n}\n\nfunc isValidClientCloseCode(code int) bool {\n\treturn code == 1000 || (code >= 3000 && code <= 4999)\n}\n\nfunc isValidCloseReason(reason string) bool {\n\treturn len([]byte(reason)) <= 123\n}\n\nfunc (w *webSocket) close(code int, reason string) error {\n\tif w.readyState == CLOSED || w.readyState == CLOSING {\n\t\treturn nil\n\t}\n\n\tif code != 0 && !isValidClientCloseCode(code) {\n\t\treturn fmt.Errorf(\n\t\t\t\"InvalidAccessError: Failed to execute 'close' on 'WebSocket': \"+\n\t\t\t\t\"The close code must be either 1000, or between 3000 and 4999. %d is neither\",\n\t\t\tcode,\n\t\t)\n\t}\n\n\tif !isValidCloseReason(reason) {\n\t\treturn errors.New(\n\t\t\t`SyntaxError: Failed to execute 'close' on 'WebSocket': The message must not be greater than 123 bytes`,\n\t\t)\n\t}\n\n\tif code == 0 {\n\t\tcode = websocket.CloseNormalClosure\n\t}\n\n\tw.readyState = CLOSING\n\tw.closeCode = code","sourceCodeStart":780,"sourceCodeEnd":816,"githubUrl":"https://github.com/grafana/k6/blob/165bb3c1a492b7a4823907fe1e93a30645794737/internal/js/modules/k6/websockets/websockets.go#L780-L816","documentation":"Close-code validation in webSocket.close: before initiating the closing handshake, the requested code is checked against isValidClientCloseCode, which accepts only 1000 or codes in the 3000–4999 range (per RFC 6455, codes 1001–2999 are reserved for protocol/server/browser use and cannot be set by client scripts). The %d shows the rejected code; the message deliberately mimics the browser DOMException InvalidAccessError.","triggerScenarios":"Thrown at internal/js/modules/k6/websockets/websockets.go:773 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use code 1000 for a normal closure","Use a custom application code between 3000 and 4999","Omit the code entirely (ws.close()) to close with the default 1000","Never send reserved codes such as 1001, 1002, or 2000–2999 from the client"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"165bb3c1a492b7a4823907fe1e93a30645794737","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}