elastic/elasticsearch · critical · LinkageError

Native function [ ] could not be found

Error message

Native function [{}] could not be found

What it means

Thrown as a LinkageError by VecCapsSymbolResolver.resolve() when no capability-level variant (base name, _2, _3, ...) of a requested vector SIMD function is found in the loaded native library via SymbolLookup. This is a fatal startup error: the Java foreign-linker downcall cannot be bound to any native symbol, meaning the simdvec shared library is missing, corrupted, or built without the required kernel.

Solutions

  1. Ensure the native simdvec library is packaged and on the library path. Check with 'ldd' / 'otool -L' / 'dumpbin'.
  2. Rebuild the native library from the libs/native source for the target platform and architecture.
  3. Inspect exported symbols: 'nm -D libsimdvec.so | grep vec_' to confirm the kernel names exist.
  4. Verify VecCaps.caps() returns a valid capability level for the CPU (check CPUID/flags).
  5. If running a custom distribution, confirm the build system includes the native compilation step.

Example fix

// No code fix; this is a deployment/build issue.
// Verify the library is loadable:
//   java -XshowSettings:properties -version  # check java.library.path
//   nm -D $ES_HOME/lib/libsimdvec.so | grep vec_doti7u
// Rebuild if symbols are missing:
//   ./gradlew :libs:native:build
Defensive patterns

Strategy: try-catch

Validate before calling

// Before relying on native vector kernels, verify the library loads:
try {
    System.loadLibrary("simdvec");
} catch (UnsatisfiedLinkError e) {
    logger.error("Native simdvec library not found; vector search will use fallback", e);
}

Try / catch

try {
    simdVecLibrary = nativeAccess.getSimdVecLibrary();
} catch (LinkageError e) {
    logger.error("Failed to bind native vector kernels; falling back to Java implementation", e);
    simdVecLibrary = null; // use pure-Java fallback
}

Prevention

When it happens

Trigger: Occurs during NativeAccessService/SimdVecLibrary initialization when the Panama FFI binder tries to resolve any @Function-annotated method. The resolver iterates from VecCaps.caps() down to 1, appending _N suffixes, and throws LinkageError if none match an exported symbol.

Common situations: Custom distribution build that omits or fails to compile the native simdvec library. Architecture mismatch (library compiled for AVX-512 but running on AVX2-only CPU, or vice versa). Library version skew between Java bindings and native code. Container image stripping the .so/.dylib/.dll. Corrupted library file.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/80a187558f2b5e0a. Report an issue: GitHub.

Appendix: source

Thrown at libs/native/src/main/java/org/elasticsearch/nativeaccess/VecCapsSymbolResolver.java:50

     * starting from the supported capability level N, it looks up function_N, function_{N-1}... function.
     *
     * @param functionName the base function name, as exported by the native library
     * @return             a {@link ResolvedSymbol} with the resolved named and address of the native function
     */
    @Override
    public ResolvedSymbol resolve(String functionName, SymbolLookup lookup) {
        int capability = VecCaps.caps();
        for (int caps = capability; caps > 0; --caps) {
            var suffix = caps > 1 ? "_" + caps : "";
            var fullFunctionName = functionName + suffix;
            logger.trace("Lookup for {}", fullFunctionName);
            var function = lookup.find(functionName + suffix).orElse(null);
            if (function != null) {
                logger.debug("Binding {}", fullFunctionName);
                return new ResolvedSymbol(fullFunctionName, function);
            }
        }
        throw new LinkageError("Native function [" + functionName + "] could not be found");
    }
}

View on GitHub (pinned to db6a809a66)