slint-ui/slint · error · std::io::Error

<js error message>

Error message

<js error message>

What it means

This error surfaces a JavaScript promise rejection from a user-supplied file loader callback back into Rust as an std::io::Error. When compile_from_string_with_style encounters an import that the JS `load_callback` must fetch asynchronously, a rejected promise means the file could not be loaded (e.g. network failure, 404, or JS exception). The rejected JsValue's string message becomes the io::Error's message and is propagated to the caller of the Slint WASM compiler API.

Solutions

  1. Inspect the error message; it is the stringified JS rejection reason — fix the underlying loader failure (wrong URL, 404, CORS).
  2. Verify the JS file loader always returns a Promise<string> of file contents for every requested path.
  3. Add try/catch or .catch() around fetch logic in the loader and return a descriptive error message.
  4. Ensure imported files exist on the server or are embedded/inlined so the loader is never called for missing assets.

Example fix

// before
load: (name) => fetch('/ui/' + name).then(r => r.text())
// after
load: (name) => fetch('/ui/' + name).then(r => {
  if (!r.ok) throw new Error(`failed to load ${name}: HTTP ${r.status}`);
  return r.text();
}).catch(e => { throw new Error('slint file loader: ' + e.message); })
Defensive patterns

Strategy: try-catch

Validate before calling

// JS: verify the loader resolves every path with a string
const res = await load_callback('App.slint');
if (typeof res !== 'string') throw new Error('loader must return a string');

Type guard

function isLoaderResult(v) { return v instanceof Promise; }

Try / catch

try { await instance.compile(source, style); } catch (e) { console.error('slint load failed:', e.message); }

Prevention

When it happens

Trigger: Calling compile_from_string (via the wasm-interpreter API) on .slint source that imports other files, where the registered JS file loader returns a rejected Promise, throws inside the async loader, or resolves to a non-string value (as_string().unwrap_or_default() yields an empty message).

Common situations: Web apps loading .slint files over HTTP with fetch-based loaders that hit 404s, CORS rejections, or offline conditions; loader code throwing TypeErrors; passing a loader that resolves with a Blob/arraybuffer instead of a string.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16). Data as JSON: /api/errors/3ceaecff1d0cfdd9. Report an issue: GitHub.

Appendix: source

Thrown at api/wasm-interpreter/src/lib.rs:95

    compiler.compiler_configuration(i_slint_core::InternalToken).is_preview = true;
    if !style.is_empty() {
        compiler.set_style(style)
    }

    if let Some(load_callback) = optional_import_callback {
        let open_import_callback = move |file_name: &Path| -> core::pin::Pin<
            Box<dyn core::future::Future<Output = Option<std::io::Result<String>>>>,
        > {
            Box::pin({
                let load_callback = js_sys::Function::from(load_callback.clone());
                let file_name: String = file_name.to_string_lossy().into();
                async move {
                    let result = load_callback.call1(&JsValue::UNDEFINED, &file_name.into());
                    let promise: js_sys::Promise = result.unwrap().into();
                    let future = wasm_bindgen_futures::JsFuture::from(promise);
                    match future.await {
                        Ok(js_ok) => Some(Ok(js_ok.as_string().unwrap_or_default())),
                        Err(js_err) => Some(Err(std::io::Error::new(
                            std::io::ErrorKind::Other,
                            js_err.as_string().unwrap_or_default(),
                        ))),
                    }
                }
            })
        };
        compiler.set_file_loader(open_import_callback);
    }

    let c = compiler.build_from_source(source, base_url.into()).await;

    let line_key = JsValue::from_str("lineNumber");
    let column_key = JsValue::from_str("columnNumber");
    let message_key = JsValue::from_str("message");
    let file_key = JsValue::from_str("fileName");
    let level_key = JsValue::from_str("level");
    let mut error_as_string = String::new();

View on GitHub (pinned to bb937076de)