BoundaryML/baml · error · JwtError

Missing crypto API

Error message

Missing crypto API

What it means

JwtError::NoCrypto is returned when the window exists but the WebCrypto API (window.crypto or crypto.subtle) is unavailable. SubtleCrypto is required for signing JWTs and is only exposed in secure contexts.

Source

Thrown at engine/baml-runtime/src/internal/wasm_jwt.rs:33

use js_sys::{Array, Object, Uint8Array};
use serde::{Deserialize, Serialize};
use serde_json::json;
use thiserror::Error;
use wasm_bindgen::JsValue;
use wasm_bindgen_futures::JsFuture;
use web_sys::{window, CryptoKey, SubtleCrypto};

#[derive(Error, Debug)]
pub enum JwtError {
    #[error("JavaScript error: {0:?}")]
    JsError(JsValue),
    #[error("Base64 decode error: {0}")]
    Base64Error(#[from] base64::DecodeError),
    #[error("JSON error: {0}")]
    JsonError(#[from] serde_json::Error),
    #[error("Missing window object")]
    NoWindow,
    #[error("Missing crypto API")]
    NoCrypto,
}

impl From<JsValue> for JwtError {
    fn from(err: JsValue) -> Self {
        JwtError::JsError(err)
    }
}

pub async fn encode_jwt(
    claims: &serde_json::Value,
    private_key_pem: &str,
) -> Result<String, JwtError> {
    // Extract the crypto.subtle API
    let window = window().ok_or(JwtError::NoWindow)?;
    let crypto = window.crypto()?;
    let subtle = crypto.subtle();

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Serve the application over HTTPS (or http://localhost, which is a secure context).
  2. Check window.crypto?.subtle at startup and show a clear feature-unsupported message.
  3. Upgrade to a browser that implements the Web Crypto API.
  4. If stuck on http, proxy through a TLS-terminating server for development.

Example fix

// before
let crypto = window.crypto().unwrap();
// after
let crypto = window.crypto().ok_or(JwtError::NoCrypto)?;
let subtle = crypto.subtle().ok_or(JwtError::NoCrypto)?;
Defensive patterns

Strategy: validation

Validate before calling

if (!window.isSecureContext || !window.crypto?.subtle) {
  throw new Error("NoCrypto: WebCrypto requires a secure context (HTTPS)");
}

Type guard

function cryptoAvailable(w) {
  return !!w.crypto && !!w.crypto.subtle;
}

Try / catch

try {
  const key = await importKey(rawKey);
} catch (e) {
  if (!window.crypto?.subtle) showHttpsWarning();
  else throw e;
}

Prevention

When it happens

Trigger: Accessing window.crypto.subtle on a page served over plain http:// (insecure origin); very old browsers lacking WebCrypto; embedded webviews with crypto disabled.

Common situations: Local development served over http on non-localhost hosts (e.g. LAN IP); testing in an embedded WebView; corporate browser policies disabling crypto.subtle.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/5282433a8372f39f. Report an issue: GitHub.