grafana/k6 · error
failed to extract algorithm: %w
Error message
failed to extract algorithm: %w
What it means
Thrown by k6 WebCrypto when exporting a symmetric key to JWK and the algorithm-to-'alg' mapping fails. exportSymmetricJWK (internal/js/modules/k6/webcrypto/jwk.go:83-86) calls extractAlg to derive the alg identifier (e.g. HS256 for HMAC/SHA-256, A256GCM for 256-bit AES-GCM); the wrapped inner error is one of: hash algorithm name shorter than 4 chars, named algorithm shorter than 4 chars, or 'unsupported algorithm'. This is essentially an internal consistency check — a well-formed key generated/imported through the normal API always carries a mappable algorithm.
Source
Thrown at internal/js/modules/k6/webcrypto/jwk.go:85
// exportSymmetricJWK exports a symmetric key as a map of JWK key parameters.
func exportSymmetricJWK(key *CryptoKey) (*JsonWebKey, error) {
rawKey, ok := key.handle.([]byte)
if !ok {
return nil, errors.New("key's handle isn't a byte slice")
}
// wrap result into the object that is expected to be returned
exported := &JsonWebKey{}
exported.Set("k", base64URLEncode(rawKey))
exported.Set("kty", JWKOctKeyType)
exported.Set("ext", key.Extractable)
exported.Set("key_ops", key.Usages)
algV, err := extractAlg(key.Algorithm, len(rawKey))
if err != nil {
return nil, fmt.Errorf("failed to extract algorithm: %w", err)
}
exported.Set("alg", algV)
return exported, nil
}
func extractAlg(inAlg any, keyLen int) (string, error) {
switch alg := inAlg.(type) {
case hasHash:
v := alg.hash()
if len(v) < 4 {
return "", errors.New("length of hash algorithm is less than 4: " + v)
}
return "HS" + v[4:], nil
case hasAlg:
v := alg.alg()
if len(v) < 4 {
return "", errors.New("length of named algorithm is less than 4: " + v)View on GitHub (pinned to 93accf6570)
Solutions
- As a workaround, export symmetric keys as 'raw' (base64url the bytes yourself) instead of 'jwk'.
- Recreate the key through the standard path — generateKey or importKey('raw'|'jwk') with a canonical algorithm name — then export 'jwk' again.
- If it reproduces with a normally-created key, file a k6 issue with the algorithm dictionary used.
Example fix
// before
const jwk = await crypto.subtle.exportKey('jwk', key); // failed to extract algorithm
// after
const raw = await crypto.subtle.exportKey('raw', key);
const jwk = { kty: 'oct', k: bytesToBase64url(new Uint8Array(raw)) }; Defensive patterns
Strategy: fallback
Try / catch
let exported;
try {
exported = await crypto.subtle.exportKey('jwk', key);
} catch (e) {
if (/failed to extract algorithm/.test(e.message)) {
const raw = await crypto.subtle.exportKey('raw', key);
exported = { kty: 'oct', k: bytesToBase64url(new Uint8Array(raw)) };
} else throw e;
} Prevention
- Prefer 'raw' export for symmetric keys; 'jwk' adds an alg-mapping step that can fail.
- Create keys only via generateKey/importKey with canonical algorithm names.
When it happens
Trigger: crypto.subtle.exportKey('jwk', symmetricKey) where the key's algorithm object was constructed through an unusual path — e.g. an imported raw key whose algorithm identifier got a truncated/nonstandard name, or a CryptoKey obtained from a nonstandard extension. Keys created by k6's own generateKey/importKey do not hit it.
Common situations: Interoperating with scripts that pass algorithm objects they built by hand (deep-cloning and mutating algorithm dictionaries); k6 version skew where a custom build changed algorithm names; extremely rare in vanilla k6 usage.
Related errors
- unsupported algorithm: %v
- curve not supported for converting to ECDSA key
- key (k) is required
- unable to convert ECDH public key to ECDSA public key, curve
- invalid key type: %s
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/34b27e87bbcafe3e.
Report an issue: GitHub.