Skip to content

Troubleshooting (Go)

The ccl package resolves libccl.dylib / libccl.so / libccl.dll at runtime, once per process, in this order:

  1. CCL_LIB_PATH — a directory containing the library, or the library file itself. If set but the file isn’t there, resolution fails hard (no fallback) — this is the way to run against a locally built library.
  2. The per-version cache: os.UserCacheDir()/cardano-client-bindings/<version>/ (e.g. ~/Library/Caches/... on macOS, ~/.cache/... on Linux).
  3. A one-time download of the release tarball from GitHub releases, extracted atomically into the cache.

The downloaded release tag is pinned in the wrapper (kept in lockstep with the wrapper version); override it with CCL_LIB_VERSION (e.g. CCL_LIB_VERSION=v0.1.0-pre4).

On Linux, musl (Alpine) is detected automatically by checking for the musl dynamic loader, and the linux-musl-x86_64 artifact is downloaded instead of the glibc one.

Environment variables:

VariableEffect
CCL_LIB_PATHUse a local library instead of the cache/download
CCL_LIB_VERSIONOverride the pinned release tag to download
CCL_SKIP_VERSION_CHECKSkip the wrapper ↔ native-lib version compatibility check

CCL_LIB_PATH is authoritative: when set, nothing else is tried. Point it at the directory that actually contains libccl.so/libccl.dylib (typically core/build/native/nativeCompile in a source checkout), or unset it to use the downloaded library.

The first ccl.New() needs network access to GitHub releases (a one-time, per-version download). In restricted environments, either pre-populate the cache directory, or build from source and set CCL_LIB_PATH. The download is atomic (temp file + rename), so a killed process can’t leave a corrupt library behind.

No prebuilt artifact exists for your platform (see matrix below). Build from source and set CCL_LIB_PATH.

The wrapper and the native library must match on base semver. This usually means CCL_LIB_PATH points at a stale build, or CCL_LIB_VERSION pins an old tag. Rebuild/repin, or (at your own risk) set CCL_SKIP_VERSION_CHECK=1.

Something called the bridge after Close(). Check with errors.Is(err, ccl.ErrBridgeClosed). Keep the bridge alive for as long as callers use it — the guard exists because handing a stale isolate handle to the native side would crash the process.

ErrTxBuild — the TxPlan didn’t build. Usual causes:

  • Malformed YAML or a wrong intent field name (check against the TxPlan reference).
  • A Plutus transaction with wrong/missing execution units.
  • CCL Error -8 (ErrInsufficientFunds) means the supplied UTXOs can’t cover outputs + fee.

Early revisions of the module had a stale internal pin that broke go get. Update to the latest tagged version; the pin is now enforced by CI.

Needed only on platforms without a prebuilt library or for development against the bridge itself:

Terminal window
git clone https://github.com/bloxbean/cardano-client-bindings
cd cardano-client-bindings
sdk install java 25.0.3-graal # GraalVM with native-image
./gradlew :core:nativeCompile # → core/build/native/nativeCompile/libccl.*
export CCL_LIB_PATH=$PWD/core/build/native/nativeCompile
GOOS/GOARCHPrebuiltNotes
linux/amd64 (glibc ≥ 2.17)RHEL/CentOS 7+, Ubuntu 18.04+, Debian 9+, Amazon Linux 2, …
linux/arm64 (glibc ≥ 2.17)
linux/amd64 (musl / Alpine)auto-detected
linux/arm64 (musl)GraalVM --libc=musl is x86_64-only
darwin/arm64 (Apple Silicon)
darwin/amd64 (macOS Intel)Oracle GraalVM dropped Intel Macs
windows/amd64