BoundaryML/baml · error · RuntimeCallbackError

JS callback error: {name}: {message}

Error message

JS callback error: {name}: {message}

What it means

RuntimeCallbackError::JsCallbackRuntimeError carries an actual exception thrown by the JS credential provider callback. The bridge deserializes the `error` branch of JsCallbackResult (js_callback_provider.rs:11-12, 17-20) into `name` and `message` fields, so the JS-side error type name and message are preserved across the WASM boundary and rethrown in Rust.

Source

Thrown at engine/baml-runtime/src/types/js_callback_provider.rs:35

pub struct JsCallbackError {
    pub name: String,
    pub message: String,
}

#[derive(Debug, Error, Clone)]
/// For baml-src-reader and aws-cred-provider, provide a statically defined type which is Send + Sync
/// anyhow::Error is not Send + Sync, so it's convoluted to use it in this callback context
pub enum RuntimeCallbackError {
    #[error("Failed to send cred request across WASM bridge: {0}")]
    SendError(String),

    #[error("Failed to recv cred response across WASM bridge: {0}")]
    RecvError(String),

    #[error("Type error in JS callback: {0}")]
    JsCallbackTypeError(String),

    #[error("JS callback error: {name}: {message}")]
    JsCallbackRuntimeError { name: String, message: String },

    #[error("BAML internal error - credential provider bridges not initialized")]
    NoCredProviderBridge,
}

static_assertions::assert_impl_all!(RuntimeCallbackError: Send, Sync);

pub type RuntimeCallbackResult<T> = Result<T, RuntimeCallbackError>;

static JS_CALLBACK_PROVIDER_SINGLETON: OnceLock<JsCallbackProvider> = OnceLock::new();

pub fn get_js_callback_provider() -> Result<&'static JsCallbackProvider, RuntimeCallbackError> {
    JS_CALLBACK_PROVIDER_SINGLETON
        .get()
        .ok_or(RuntimeCallbackError::NoCredProviderBridge)
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Read `name` and `message` in the error to identify the JS-side failure (e.g. missing AWS profile, expired token) and fix that root cause.
  2. Verify AWS credentials exist: check ~/.aws/credentials for the requested profile, or set AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN env vars.
  3. For GCP, ensure GOOGLE_APPLICATION_CREDENTIALS points to a valid service-account JSON key.
  4. If using a custom provider, add try/catch and logging in the JS callback to surface clearer error messages.
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check AWS/GCP credentials on the JS side before invoking BAML
try { await fromIni({ profile: 'my-profile' })(); } catch (e) { console.error('AWS profile unavailable:', e.message); }
if (!process.env.GOOGLE_APPLICATION_CREDENTIALS && !process.env.GCP_ACCESS_TOKEN) console.warn('GCP credentials not configured');

Try / catch

// inspect the propagated JS error name/message
try {
  const result = await b.GenerateSummary(input);
} catch (e) {
  if (String(e).startsWith('JS callback error:')) {
    console.error('Credential provider failed:', e.message); // e.g. 'CredentialsProviderError: Could not load credentials'
    // fall back to alternate credentials or fail fast with a clear message
  } else { throw e; }
}

Prevention

When it happens

Trigger: The JS-side AWS/GCP credential provider throws or its promise rejects; the bridge serializes it as `{"error": {"name", "message"}}`, and `aws_req`/`gcp_req` return it via the `Ok(Err(e))` branch (js_callback_provider.rs:107-110 and 130-133) as `JsCallbackRuntimeError { name, message }`.

Common situations: AWS `fromIni` fails because the profile is missing from ~/.aws/credentials, the container has no AWS credentials/env configured (`CredentialsProviderError`), GCP auth fails due to missing GOOGLE_APPLICATION_CREDENTIALS, or the custom JS provider itself throws on network/permission errors.

Related errors


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