wasmerio/wasmer · error

Internal error: $ORIGIN or ${{ORIGIN}} in RUNPATH, but no ca

Error message

Internal error: $ORIGIN or ${{ORIGIN}} in RUNPATH, but no calling module path provided

What it means

locate_module expands $ORIGIN/${ORIGIN} in a RUNPATH to the directory of the calling module. If the RUNPATH contains $ORIGIN but no calling module path was provided, the code panics. The comment explains why: the only legitimate case of an empty calling_module_path is a top-level dlopen, and a dlopen'ed module has no RUNPATH-dependent requirer, so reaching this branch indicates a broken invariant in load_module_tree's invocation.

Source

Thrown at lib/wasix/src/state/linker/locator.rs:99

            .as_ref()
            .map(|p| p.as_ref().parent().unwrap_or_else(|| p.as_ref()));

        let runtime_path = runtime_path.iter().map(|path| {
            let path = path.as_ref();

            let relative = path
                .strip_prefix("$ORIGIN")
                .or_else(|| path.strip_prefix("${ORIGIN}"));

            match relative {
                Some(relative) => {
                    let Some(calling_module_dir) = calling_module_dir else {
                        // This is an internal error because the only time calling_module_path
                        // should be empty is when loading a module through dlopen, and a
                        // dlopen'ed module isn't being required by another module so we don't
                        // have a RUNPATH to consider at all. See the invocation of
                        // `load_module_tree` in `load_module`.
                        panic!(
                            "Internal error: $ORIGIN or ${{ORIGIN}} in RUNPATH, but \
                            no calling module path provided"
                        );
                    };
                    Cow::Owned(PathBuf::from(
                        fs.relative_path_to_absolute(
                            calling_module_dir
                                .join(relative)
                                .to_string_lossy()
                                .into_owned(),
                        ),
                    ))
                }
                None => Cow::Borrowed(Path::new(path)),
            }
        });

        // Search order is: LD_LIBRARY_PATH -> RUNPATH -> system default folders

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Provide the calling module path when invoking load_module_tree so $ORIGIN can be expanded (see the load_module invocation site)
  2. If loading via dlopen, avoid $ORIGIN in RUNPATH for top-level modules or pass the .so's own directory as the calling path
  3. Rebuild the shared library to use an absolute RUNPATH if it is only ever dlopen'ed directly
  4. If it occurs during a nested require, report it as a linker bug with the module dependency chain

Example fix

// before: dlopen'ing a module whose RUNPATH uses $ORIGIN, no calling path
let m = linker.load_module("/opt/app/libfoo.so")?; // RUNPATH=$ORIGIN/../lib
// after: pass the calling module path so $ORIGIN resolves
let m = linker.load_module_with_calling_path(
    "/opt/app/libfoo.so",
    Path::new("/opt/app/libfoo.so"),
)?;
Defensive patterns

Strategy: validation

Validate before calling

fn runpath_needs_calling_path(runpath: &str) -> bool {
    runpath.contains("$ORIGIN") || runpath.contains("${ORIGIN}")
}
// before loading: if runpath_needs_calling_path(&runpath) {
//     ensure load_module_tree is invoked with Some(calling_module_path)
// }

Type guard

fn has_calling_path(p: &Option<PathBuf>) -> bool {
    p.as_ref().map_or(false, |p| !p.as_os_str().is_empty())
}

Prevention

When it happens

Trigger: load_module_tree invoked (via locate_module) to resolve a module whose RUNPATH entry contains $ORIGIN while calling_module_dir is None; a nested require chain where an intermediate module lost its path context.

Common situations: A .so's RUNPATH using $ORIGIN being loaded via plain dlopen rather than through the linker's module-tree loading path; a custom loader invocation passing no calling module path where RUNPATH resolution is needed; misbuilt shared library with $ORIGIN RUNPATH that should not be resolved relative to a requirer.

Related errors


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/91a096f10067512b. Report an issue: GitHub.