{"record":{"id":"d80bf6b961c48cbf","repo":"gchq/CyberChef","slug":"data-is-not-a-valid-tls-server-hello-quic-is-not","errorCode":null,"errorMessage":"Data is not a valid TLS Server Hello. QUIC is not yet supported.\\n${err}","messagePattern":"Data is not a valid TLS Server Hello\\. QUIC is not yet supported\\.\\\\n(.+?)","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/JA4.mjs","lineNumber":175,"sourceCode":"        \"JA4_ro\": `${ptype}${version}${sni}${cipherLen}${extLen}${alpn}_${originalCiphersRaw}_${originalExtensionsRaw}`,\n    };\n}\n\n\n/**\n * Calculate the JA4Server from a given TLS Server Hello Stream\n * @param {Uint8Array} bytes\n * @returns {string}\n */\nexport function toJA4S(bytes) {\n    let tlsr = {};\n    try {\n        tlsr = parseTLSRecord(bytes);\n        if (tlsr.handshake.value.handshakeType.value !== 0x02) {\n            throw new Error();\n        }\n    } catch (err) {\n        throw new OperationError(\"Data is not a valid TLS Server Hello. QUIC is not yet supported.\\n\" + err);\n    }\n\n    /* QUIC\n        “q” or “t”, which denotes whether the hello packet is for QUIC or TCP.\n        TODO: Implement QUIC\n    */\n    const ptype = \"t\";\n\n    /* TLS Version\n        TLS version is shown in 3 different places. If extension 0x002b exists (supported_versions), then the version\n        is the highest value in the extension. Remember to ignore GREASE values. If the extension doesn’t exist, then\n        the TLS version is the value of the Protocol Version. Handshake version (located at the top of the packet)\n        should be ignored.\n    */\n    let version = tlsr.handshake.value.helloVersion.value;\n    for (const ext of tlsr.handshake.value.extensions.value) {\n        if (ext.type.value === \"supported_versions\") {\n            version = parseHighestSupportedVersion(ext.value.data);","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/JA4.mjs#L157-L193","documentation":"Thrown by toJA4S, the Server Hello counterpart of toJA4. It wraps parseTLSRecord in a try/catch and requires handshakeType === 0x02 (ServerHello); any parse failure or non-ServerHello record is re-thrown as an OperationError with the original error appended. QUIC is not supported.","triggerScenarios":"Passing a Client Hello (type 0x01), a Certificate/Alert/ApplicationData record, a QUIC Initial, a truncated capture, or non-TLS bytes.","commonSituations":"Selecting the wrong packet from a PCAP; feeding a Client Hello to the Server Hello function; QUIC traffic; incomplete TCP reassembly; encrypted record mistaken for a handshake.","solutions":["Confirm the bytes are a Server Hello (handshake type 0x02) and a complete TLS record.","Use toJA4 for Client Hello inputs.","Reassemble the TCP stream before extracting the record.","Filter out QUIC traffic (use a QUIC-aware tool instead)."],"exampleFix":"// before\ntoJA4S(clientHelloBytes); // wrong direction\n\n// after\ntoJA4(clientHelloBytes);","handlingStrategy":"try-catch","validationCode":"function looksLikeServerHello(bytes) {\n  return bytes.length >= 11 &&\n    bytes[0] === 0x16 &&               // ContentType: Handshake\n    bytes[1] === 0x03 &&               // Protocol version TLS (3.x)\n    bytes[5] === 0x02 &&               // HandshakeType: ServerHello\n    Number.isInteger(bytes[6]);\n}\nif (!looksLikeServerHello(bytes)) throw new Error(\"Not a TLS Server Hello record\");\ntoJA4S(bytes);","typeGuard":"const isLikelyServerHello = bytes =>\n  bytes.length >= 11 && bytes[0] === 0x16 && bytes[5] === 0x02;","tryCatchPattern":"try {\n  toJA4S(bytes);\n} catch (err) {\n  if (err instanceof OperationError && /not a valid TLS Server Hello/.test(err.message)) {\n    // wrong packet direction, truncated, QUIC, or non-TLS; re-select input\n  } else throw err;\n}","preventionTips":["Select the Server Hello (handshake type 0x02) from the capture, not the Client Hello.","Reassemble the TCP stream so the TLS record is complete.","Filter out QUIC; it is explicitly unsupported."],"tags":["tls","ja4","networking","fingerprinting","quic"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}