risingwavelabs/risingwave · critical

not root

Error message

not root

What it means

locate_libs_path derives the JVM `libs` directory relative to the current executable path. After canonicalizing the executable path it calls .parent().expect("not root"), so the process panics with `not root` if the executable sits directly in the filesystem root directory — its path has no parent component. This is an internal invariant that should never hold in a normal installation.

Solutions

  1. Move the binary into a subdirectory (e.g. /opt/risingwave/risingwave) so its path has a parent.
  2. Alternatively set CONNECTOR_LIBS_PATH explicitly to skip executable-relative resolution.
  3. Restore the standard installation layout (binary next to a `libs` directory).
  4. Keep binary and `libs` folder siblings in any custom packaging.

Example fix

// before
COPY risingwave /risingwave
// after
COPY risingwave /opt/risingwave/risingwave && COPY libs /opt/risingwave/libs
Defensive patterns

Strategy: validation

Validate before calling

import os, sys
exe = os.path.realpath(sys.argv[0])
parent = os.path.dirname(exe)
assert parent not in ('/', ''), 'binary must not live at filesystem root; move it or set CONNECTOR_LIBS_PATH'

Prevention

When it happens

Trigger: Running the RisingWave binary from the filesystem root (e.g. copied to /risingwave or /) so std::env::current_exe().parent() returns None, triggering the expect panic during build_jvm_with_native_registration.

Common situations: Container images that place the binary at /, custom deployments relocating the binary, docker ENTRYPOINT copying the binary to root instead of /usr/local/bin.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/01440ab3f30367dd. Report an issue: GitHub.

Appendix: source

Thrown at src/jni_core/src/jvm_runtime.rs:45

use crate::opendal_schema_history::*;
use crate::{call_method, call_static_method};

/// Use 10% of compute total memory by default. Compute node uses 0.7 * system memory by default.
const DEFAULT_MEMORY_PROPORTION: f64 = 0.07;

fn locate_libs_path() -> anyhow::Result<PathBuf> {
    let libs_path = if let Ok(libs_path) = std::env::var("CONNECTOR_LIBS_PATH") {
        PathBuf::from(libs_path)
    } else {
        tracing::info!(
            "environment variable CONNECTOR_LIBS_PATH is not specified, use default path `./libs` instead"
        );
        std::env::current_exe()
            .and_then(|p| p.fs_err_canonicalize()) // resolve symlink of the current executable
            .context("unable to get path of the executable")?
            .parent()
            .expect("not root")
            .join("libs")
    };
    Ok(libs_path)
}

fn build_jvm_with_native_registration() -> anyhow::Result<JavaVM> {
    let libs_path = locate_libs_path().context("failed to locate connector libs")?;
    tracing::info!(path = %libs_path.display(), "located connector libs");

    let mut class_vec = vec![];

    let entries = fs::read_dir(&libs_path).context(if cfg!(debug_assertions) {
        "failed to read connector libs; \
        for RiseDev users, please check if ENABLE_BUILD_RW_CONNECTOR is set with `risedev configure`"
    } else {
        "failed to read connector libs, \
        please check if env var CONNECTOR_LIBS_PATH is correctly configured"
    })?;

View on GitHub (pinned to 6469eb736d)