tursodatabase/turso · critical · InternalError
Unable to load necessary native library
Error message
Unable to load necessary native library
What it means
InternalError thrown from the lazy SingletonHolder static block when both loadFromSystemPath() and loadFromJar() fail, meaning the _turso_java native library was found neither on java.library.path nor inside the JAR for the detected OS/architecture. Because it fires in a static initializer, it surfaces as InternalError at whatever line first forces TursoDB class initialization (typically opening a database). Unlike the architecture throw, this one means the library files exist for the platform in principle but could not be located or extracted.
Solutions
- Verify the detected Architecture matches the host (see the separate ARM64-on-Linux throw)
- Place a working libturso_java.so on the library path: start the JVM with -Djava.library.path=/path/to/lib so loadFromSystemPath() succeeds
- Unzip the JAR and confirm it contains the native resource for your OS/arch; repair or re-pin the Maven/Gradle dependency if missing
- Ensure the extraction directory is writable and executable: -Djava.io.tmpdir pointing to an exec-mounted path
- Catch InternalError (and UnsatisfiedLinkError) at startup and fail fast, logging os.arch, java.library.path, and java.io.tmpdir
Example fix
// before
TursoDB db = TursoDB.open(path); // InternalError on first use
// after
try {
TursoDB db = TursoDB.open(path);
} catch (InternalError | UnsatisfiedLinkError e) {
throw new IllegalStateException("native load failed; os.arch="
+ System.getProperty("os.arch")
+ ", java.library.path=" + System.getProperty("java.library.path")
+ ", tmpdir=" + System.getProperty("java.io.tmpdir"), e);
} Defensive patterns
Strategy: try-catch
Validate before calling
static boolean systemPathHasNative() {
try {
System.loadLibrary("_turso_java");
return true;
} catch (UnsatisfiedLinkError e) {
return false;
}
}
// call before first use: if false, verify the JAR carries natives for your os/arch
// and that java.io.tmpdir is writable+executable before letting TursoDB initialize Try / catch
try {
TursoDB db = TursoDB.open(path);
} catch (InternalError | UnsatisfiedLinkError e) {
// note: InternalError is an Error, not an Exception — catch it explicitly
throw new IllegalStateException(
"native library load failed; os.arch=" + System.getProperty("os.arch")
+ ", java.library.path=" + System.getProperty("java.library.path")
+ ", tmpdir=" + System.getProperty("java.io.tmpdir"), e);
} Prevention
- Force TursoDB class initialization once inside a guarded startup block, never lazily on the first query
- Keep the container temp directory writable and exec-mounted
- Verify shaded/uber-jars keep the embedded native resources after repackaging
- Log os.arch, java.library.path, and java.io.tmpdir in startup diagnostics
When it happens
Trigger: java.library.path does not contain libturso_java.so and the JAR lacks a native resource matching Architecture.detect(); the temp directory used for extraction is read-only or mounted noexec; the JAR is corrupted or was shaded/repackaged in a way that dropped the embedded natives resource.
Common situations: Uber-jars and shadow-plugin builds stripping native resources; hardened containers with noexec TMPDIR; -Djava.library.path passed after JVM start or with a typo; a partial dependency download; running an x86_64-only artifact on an unsupported host.
Related errors
- step() returned null, which is only returned when an error…
- ARM64 architecture is not supported on Linux yet
- Exception while resetting statement
- Exception while retrieving number of changes
- Exception while retrieving parameter count
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/a43acc39366042e6.
Report an issue: GitHub.
Appendix: source
Thrown at bindings/java/src/main/java/tech/turso/core/TursoDB.java:110
/**
* This method attempts to load the native library required for turso operations. It first tries
* to load the library from the system's library path using {@link #loadFromSystemPath()}. If that
* fails, it attempts to load the library from the JAR file using {@link #loadFromJar()}. If
* either method succeeds, the `isLoaded` flag is set to true. If both methods fail, an {@link
* InternalError} is thrown indicating that the necessary native library could not be loaded.
*
* @throws InternalError if the native library cannot be loaded from either the system path or the
* JAR file.
*/
private static void load() {
new SingletonHolder();
}
// "lazy initialization holder class idiom" (Effective Java #83)
private static class SingletonHolder {
static {
if (!loadFromSystemPath() && !loadFromJar()) {
throw new InternalError("Unable to load necessary native library");
}
}
}
/**
* Load the native library from the system path.
*
* <p>This method attempts to load the native library named "_turso_java" from the system's
* library path. If the library is successfully loaded, the `isLoaded` flag is set to true.
*
* @return true if the library was successfully loaded, false otherwise.
*/
private static boolean loadFromSystemPath() {
try {
System.loadLibrary("_turso_java");
return true;
} catch (Throwable t) {
logger.info("Unable to load from default path: {}", String.valueOf(t));View on GitHub (pinned to 244cde92a7)