kosa8 docs

Guides / Java / Errors and troubleshooting

Java errors and troubleshooting

Everything the SDK throws is a Kosa8Exception, and an error from the daemon keeps the daemon's own words: what went wrong, and what to do about it. This page lists each class, when it is thrown and how to handle it, then the problems you are likely to meet, from symptom to fix.

How this page was tested

This page describes SDK 0.1.2 (com.kosa8:kosa8:0.1.2 on Maven Central). The capture and mount messages, which 0.1.2 changed or added, were printed by 0.1.2 built from the v0.1.2 tag (commit 14e5fc6) with mvn install, because Maven Central was still answering 404 for 0.1.2 while it was being published. Each message in a terminal block was printed by a Java program on OpenJDK 21.0.12.1, against kosa8 daemon 0.9.36 on an Apple silicon Mac (macOS 26.0.1). The messages that 0.1.1 added or changed (the failed rewind, the lock timeout, capture(true), exec with env, a second writeStdin, a bad mount) came from 0.1.1, built from its release tag just before it was published; the published jar carries the same messages (checked in its class files). The rest came from 0.1.0 from Maven Central, on code paths 0.1.1 did not change; the run, exec, stdin and timeout ones were re-run on 0.1.1 and printed the same. What changed between the two versions is listed at the end. AuthException, PolicyException, ApprovalRequiredException and UnsupportedException were not produced: that would have meant installing an org policy or a remote worker on a shared test machine. Their sections are from the SDK's source, and say so. The locked-screen rewind failure is quoted from the Go SDK's run of the same daemon.

What this is, in plain words

When something goes wrong, the SDK throws an exception. Java has two kinds: checked exceptions, which the compiler makes you catch or declare, and unchecked ones, which it does not. All of this SDK's exceptions are unchecked: your code compiles without any try/catch, and you catch only what you want to handle.

Each exception says what happened in its message. When the daemon refused something, the message also carries the daemon's advice in brackets, and the same two parts are available separately as daemonMessage() and remediation().

One thing is not an exception: a command that runs and exits with a non-zero code. That is a normal result; check result.exitCode() or result.ok().

The hierarchy

All classes are public static classes nested inside com.kosa8.Kosa8Exception, so you write Kosa8Exception.NotFoundException, or import them individually (import com.kosa8.Kosa8Exception.NotFoundException;).

java.lang.RuntimeException                 unchecked
└─ Kosa8Exception                          anything this SDK throws; used as is for client-side checks
   ├─ ConnectionException                  the daemon could not be reached
   ├─ ApiException                         the daemon answered with an HTTP error (any status, e.g. 500)
   │  ├─ BadRequestException               400
   │  ├─ AuthException                     401
   │  ├─ PolicyException                   403
   │  │  └─ ApprovalRequiredException      403 that a signed approval would lift
   │  ├─ NotFoundException                 404
   │  ├─ ConflictException                 409
   │  └─ UnsupportedException              501
   ├─ StreamException                      a run, exec or attach stream ended with an error, or broke
   ├─ CheckpointException                  checkpoint bookkeeping: none to rewind to, bad name, failed restore
   └─ TimeoutException                     a request ran out of time
Two names that clash

Kosa8Exception.TimeoutException is not java.util.concurrent.TimeoutException (which is checked). If you import both, refer to the SDK's by its qualified name. Likewise, Kosa8Exception itself extends RuntimeException, so a catch (RuntimeException e) placed first will swallow it.

Fields

AccessorOnMeaning
getMessage()allFor a daemon error: "<error> (<remediation>)", the way the CLI prints it; just <error> when there is no remediation; "request failed with HTTP <status>" when the body had no text.
status()allThe HTTP status for an ApiException; 0 for everything else (the daemon did not answer with an error status).
daemonMessage()ApiException, StreamExceptionThe daemon's error text (or message if there is no error), verbatim. For a stream, the error frame's text. null otherwise.
remediation()ApiExceptionThe daemon's advice, or null.
method(), path()ApiException, ConnectionException, TimeoutExceptionThe request that failed, as POST and /kosa8/v1/sandboxes/x/run. null on the others.
body()ApiExceptionThe decoded response body: a Map for JSON, a String otherwise.
getCause()ConnectionException, some CheckpointExceptions and plain onesThe underlying exception, as java.net.SocketException, or the restore failure inside a failed rewind.
stdout(), stderr()StreamExceptionOutput produced before the stream ended, decoded as UTF-8. Never null.
approval()ApprovalRequiredExceptionThe daemon's refusal as a map: why, who may sign, how to request one.

The program that printed the messages on this page used this helper:

static void show(String what, Kosa8Exception e) {
  System.out.println(what + ": " + e.getClass().getName().replace("com.kosa8.", "") + " status=" + e.status()
      + " method=" + e.method() + " path=" + e.path() + "\n   message: " + e.getMessage()
      + "\n   daemonMessage: " + e.daemonMessage() + "\n   remediation: " + e.remediation());
}

try { k.deleteSandbox("no-such-sandbox"); } catch (Kosa8Exception e) { show("delete missing", e); }

Each class

ConnectionException

When: the request never reached a daemon: no socket file, nothing listening, a socket path too long for the operating system, a worker that does not answer within the 30-second connect limit, or a reply that was not HTTP.

no daemon: Kosa8Exception$ConnectionException status=0 method=GET path=/kosa8/v1/health
   message: kosa8 daemon unreachable at unix:///tmp/no-daemon-here.sock: SocketException: No such file or directory (is kosa8 installed and its daemon running? start it with `kosa8 daemon start`)
   cause: java.net.SocketException: No such file or directory

Handle: start the daemon or fix the address. The hint in brackets is added when the cause looks like "nothing there". Nothing was done, so it is safe to retry once the daemon is up.

ApiException (any other status)

When: the daemon answered with an HTTP status of 400 or more that has no subclass of its own, mostly 500. kosa8 0.9.36 uses 500 for some "not found" cases, so these are not NotFoundException:

start missing: Kosa8Exception$ApiException status=500 method=POST path=/kosa8/v1/sandboxes/no-such-sandbox/up
   message: no such sandbox: no-such-sandbox (run `kosa8 doctor`; check ~/.kosa8/log/)
restore missing: Kosa8Exception$ApiException status=500 method=POST path=/kosa8/v1/snapshots/no-such-snap/restore
   message: no such snapshot: no-such-snap (list snapshots with `kosa8 snapshot ls`)

It is also what a sandbox that fails to boot looks like on a busy machine:

Exception in thread "main" com.kosa8.Kosa8Exception$ApiException: guest not ready on vsock port 1024 after 25s (run `kosa8 doctor`; check ~/.kosa8/log/)
	at com.kosa8.Kosa8Exception.fromResponse(Kosa8Exception.java:158)
	at com.kosa8.Transport.json(Transport.java:262)
	at com.kosa8.Kosa8Client.createSandbox(Kosa8Client.java:142)

Handle: read the message. Catch ApiException to handle every daemon refusal in one place; the subclasses below are all ApiExceptions.

BadRequestException (400)

When: the daemon refused a value, most often an egress rule.

bad egress: Kosa8Exception$BadRequestException status=400 method=POST path=/kosa8/v1/sandboxes
   message: egress allow "*.com": com is a public suffix, under which anyone can register a name, so the wildcard would admit strangers' hosts; allow a domain below it, as in *.example.com
   remediation: null

Handle: fix the input; retrying the same request fails the same way.

AuthException (401)

When: a remote worker rejected the bearer token, or none was sent. (From the source; not produced for this page.) The token is never sent over a unix socket, so this comes only from a worker.

Handle: check the token. A common cause: KOSA8_TOKEN is read only when the host also came from KOSA8_HOST. If your code calls builder().host(…), it must call token(…) too.

PolicyException (403)

When: the org policy forbids the action: a registry that is not allowed, an egress rule wider than the policy permits, and so on. (From the source; not produced for this page.)

Handle: the message names the policy and the rule. Retrying will not help; change the request or the policy (kosa8 policy show).

ApprovalRequiredException (403)

When: a 403 whose body carries an approval object with a why string: the action is allowed once someone signs for it. It extends PolicyException, so catch it first. (From the source; not produced for this page.)

try {
  k.pull("ghcr.io/acme/tool:1");
} catch (Kosa8Exception.ApprovalRequiredException e) {
  System.out.println("needs approval: " + e.approval().get("why"));
  // once signed:  k.pull("ghcr.io/acme/tool:1", Options.Approval.of(signature));
}

NotFoundException (404)

delete missing: Kosa8Exception$NotFoundException status=404 method=DELETE path=/kosa8/v1/sandboxes/no-such-sandbox
   message: no such sandbox: no-such-sandbox (list sandboxes with `kosa8 sandbox ls`)
run missing: Kosa8Exception$NotFoundException status=404 method=POST path=/kosa8/v1/sandboxes/no-such-sandbox/run
   message: no such sandbox: no-such-sandbox (list sandboxes with `kosa8 sandbox ls`)
delete snap missing: Kosa8Exception$NotFoundException status=404 method=DELETE path=/kosa8/v1/snapshots/no-such-snap
   message: no such snapshot: no-such-snap (list snapshots with `kosa8 snapshot ls`)

Handle: in clean-up code, a NotFoundException from a delete usually means "already gone" and can be ignored. getSandbox and sb.info() never throw this: they return null.

ConflictException (409)

dup: com.kosa8.Kosa8Exception$ConflictException 409: sandbox doc-java-snap already exists (choose another name, or remove the existing sandbox with `kosa8 sandbox rm NAME` (`kosa8 sandbox ls` lists them))

Handle: pick another name, or reuse the existing sandbox.

UnsupportedException (501)

When: the daemon (or this platform) does not support the operation. (From the source; not produced for this page.)

StreamException

When: run, exec or attach started streaming and then ended with an error frame, broke mid-stream, sent a line that is not a valid frame, or ended without a final frame. Because the daemon reports some failures inside the stream rather than as an HTTP status, these are stream errors too, with status() 0:

unpulled: com.kosa8.Kosa8Exception$StreamException status=0: image "docker.io/library/python:3.12-alpine" not found in engine: image "docker.io/library/python:3.12-alpine": not found
exec missing: com.kosa8.Kosa8Exception$StreamException status=0: no such container: nope

Handle: e.stdout() and e.stderr() hold whatever was printed before the failure; e.daemonMessage() is the error frame's text. A non-zero exit code is not a StreamException. execFrames does not throw one for an error frame either: it hands the frame to your consumer.

CheckpointException

When: client-side checkpoint bookkeeping fails, before or after the daemon is involved:

rewind none: Kosa8Exception$CheckpointException status=0 method=null path=null
   message: no checkpoints for "never-checkpointed" — take one with checkpoint() or `kosa8 checkpoint never-checkpointed`
bad name: Kosa8Exception$CheckpointException status=0 method=null path=null
   message: invalid sandbox name "../etc"

Also: no checkpoint "X" for sandbox "Y" when rewind(to) matches no id or label; update the checkpoint store … when the file cannot be written (the IOException is the cause); a lock that another process holds for longer than the store's lock timeout (10 seconds unless you built the store with new FileCheckpointStore(path, Duration)), here with a 2-second limit:

com.kosa8.Kosa8Exception$CheckpointException after 2021ms: timed out after 2s waiting for /private/tmp/…/ck/checkpoints.json.lock; another kosa8 process is holding it

and, most importantly, a failed restore during a rewind:

A rewind whose restore failed. A rewind deletes the sandbox first, then restores the checkpoint under the same name. If the restore fails, the sandbox no longer exists, and the message says so and tells you how to bring it back. To produce one for this page, the latest checkpoint's snapshot was deleted behind the SDK's back before rewinding to it:

failed rewind: com.kosa8.Kosa8Exception$CheckpointException: restore failed and doc-java-011 no longer exists (it was deleted to free its name for the restore): no such snapshot: doc-java-011-ckpt-2 (list snapshots with `kosa8 snapshot ls`) — the checkpoint is intact; recover with restoreSnapshot("doc-java-011-ckpt-2", new Options.Restore().name("doc-java-011"))
sandbox after failed rewind: null

"The checkpoint is intact" is true when the restore failed for a passing reason such as a locked screen. In this artificial case the snapshot itself was gone, so there was nothing to restore. (0.1.0 said the sandbox "is now stopped", which was wrong: it has been deleted.)

On a Mac the usual cause is a locked screen: the daemon answers macOS blocks restoring a VM while the screen is locked; unlock and retry (as seen from the Go SDK against the same daemon). Unlock, then run the call from the message:

k.restoreSnapshot("doc-java-demo-ckpt-1", new Options.Restore().name("doc-java-demo"));

The checkpoint records are not changed by a failed rewind, so rewind also works again once the cause is fixed. getCause() is the original ApiException.

If you give up instead of recovering, clean up by hand. With the sandbox gone, delete() throws NotFoundException before it reaches the checkpoint bookkeeping. The sandbox's records stay in ~/.kosa8/checkpoints.json and their snapshots stay on disk (seen). Delete the snapshots with deleteSnapshot(id, null) for each sb.checkpoints() entry, then drop the records:

new FileCheckpointStore().update(d -> d.remove("doc-java-011"));

TimeoutException

timeout: com.kosa8.Kosa8Exception$TimeoutException: POST /kosa8/v1/sandboxes/doc-java-guide/run timed out talking to unix:///Users/dhruvit/.kosa8/run/kosa8.sock

When: Options.Run.timeout or the client-wide Builder.timeout passed. Handle: the command in the sandbox keeps running: after this exception the sleep 30 container still showed status=running. Clean it up yourself. The exception carries no output; use the onStdout/onStderr callbacks to keep partial output.

Kosa8Exception itself

When: the SDK refused before sending anything, or explore could not finish. Real messages:

bad actor:   actor must be human, agent or tool, not "robot"
plain http:  refusing to talk to 10.0.0.5:8080 over plain http: the token and every request would cross the network unencrypted. Use https://10.0.0.5:8080 (a worker behind a TLS-terminating tunnel or proxy), or set insecure / KOSA8_INSECURE=1 if this link is already private and trusted
bad scheme:  KOSA8_HOST scheme "ftp" is not supported; use http://, https://, tcp:// or unix://
egress:      egressAllow already limits the network to the hosts it lists; do not also set egress
explore one: give at least two variants; with one there is nothing to compare
capture(true): capture(true) is not enough: the daemon needs a host file to write the capture to; use capture("/path/to/capture.pcapng")
capture(""): capture needs a host file path to write the capture to
bad mount:   mount "/tmp": want host:guest or host:guest:ro
relative:    mount "mnt:/work": both paths must be absolute (use Path.toAbsolutePath() for the host side)
exec env:    exec does not take env: the container keeps the environment it was started with. Set it at startInteractive, or wrap the command: List.of("env", "K=V", "cmd")
second stdin: stdin of container k3-d6cc9b51 in doc-java-011 was already sent and is closed: the daemon treats one writeStdin body as the whole of stdin. Pass an InputStream to stream input

The first three come from build(). The capture, mount, exec and stdin checks replace calls that 0.1.0 sent and that then failed or quietly did nothing. (0.1.1 worded the two capture messages as "host directory"; 0.1.2 says file, which is what the daemon writes.) Others from the source: KOSA8_HOST "…" names no host; from explore, forked N branches for M variants; see listSandboxes() for what was created, keep X is not one of the branches (…); all of them were kept, explore interrupted (the thread's interrupt flag is set again) and explore branch failed: ….

What can escape that is not a Kosa8Exception

ExceptionFromWhen
java.io.UncheckedIOExceptionFileCheckpointStore.load()The checkpoint file exists but cannot be read (permissions). A missing file is fine, and an unparseable one reads as empty.
anythingyour own CheckpointStore, your callbacksAn unchecked exception thrown by your onStdout/onStderr/onStatus callback or execFrames consumer propagates out of the call and the connection is closed. One exception to that: an IllegalArgumentException (or subclass, such as NumberFormatException) is caught by the frame reader and comes out as StreamException: bad frame from …. (From the source.)
NullPointerExceptionargumentsA null sandbox, container or snapshot id (checkpoint calls check the name first and throw CheckpointException instead), or a null variants list for explore. Options arguments may be null; ids may not.

A handling pattern

try {
  Results.Exec r = sb.run("alpine:latest", List.of("sh", "-c", script),
      new Options.Run().timeout(Duration.ofMinutes(5)));
  if (!r.ok()) log.warn("script failed with exit {}: {}", r.exitCode(), r.stderr());
} catch (Kosa8Exception.TimeoutException e) {
  log.warn("still running after 5 minutes; deleting the sandbox");
  sb.delete();
} catch (Kosa8Exception.StreamException e) {
  log.error("could not run: {} (output so far: {})", e.daemonMessage(), e.stdout());
} catch (Kosa8Exception.ApprovalRequiredException e) {
  log.info("needs a signed approval: {}", e.approval().get("why"));
} catch (Kosa8Exception.ApiException e) {
  log.error("daemon refused ({}): {}", e.status(), e.getMessage());
} catch (Kosa8Exception.ConnectionException e) {
  log.error("is the daemon running? {}", e.getMessage());
}

Order matters: put subclasses before their parents (ApprovalRequiredException before PolicyException before ApiException before Kosa8Exception), or the compiler will reject the later catch as unreachable.

Troubleshooting

Search the page for a few words of the message you see.

SymptomCauseFix
Maven: prefixes: Path com/kosa8/kosa8/0.1.0/kosa8-0.1.0.jar NOT allowed from central (the .pom downloads, the jar does not)Newer Maven resolvers check Central's list of top-level folders (/.meta/prefixes.txt) before downloading. Early on 3 November 2026 the list did not yet include the new com/kosa8 namespace, and Maven 3.10.0 refused the jar. Later that day the list included it, and a fresh local repository resolved 0.1.1 with no flags. You can still see this if your local repository or a mirror kept the old list.mvn -Daether.remoteRepositoryFilter.prefixes=false … once, or add that flag to .mvn/maven.config. Once the jar is in your local repository the flag is no longer needed.
UnsupportedClassVersionError: com/kosa8/… has been compiled by a more recent version of the Java Runtime (class file version 61.0)The jar is built for Java 17 (class file 61) and you are running an older JVM.Run on Java 17 or later. java -version shows which one your build tool uses.
ConnectionException: … SocketException: No such file or directory (is kosa8 installed and its daemon running? …)The daemon is not running, or the socket is elsewhere.kosa8 daemon start, then kosa8 daemon status. If HOME differs between your program and the daemon (a service account, a container, a test harness), pass socketPath(…). After a daemon restart every sandbox is stopped; startSandbox boots it again.
ConnectionException: … SocketException: Unix domain path too longmacOS limits a socket path to 104 bytes, and the socket is $HOME/.kosa8/run/kosa8.sock. Happens with deep temporary HOMEs in CI.Use a shorter HOME, or a short symlink to the socket's folder, for both the daemon and your program.
ApiException: guest not ready on vsock port 1024 after 25s from createSandboxThe new virtual machine did not finish booting in time; seen twice in a row while other programs were booting sandboxes on the same Mac. No sandbox was left behind.Retry; it succeeded once the machine was less busy. If it persists, kosa8 doctor and ~/.kosa8/log/.
StreamException: image "…" not found in engineThe image was never pulled into this sandbox. k.pull(ref) pulls into the host's engine, not the sandbox's.sb.pull(ref) (pullIntoSandbox) first.
StreamException: no such container: …Wrong container id, or it exited.Check sb.containers(). Keep a container alive with a long-running command such as sleep infinity.
TimeoutException, and the command is still running in the sandboxA timeout only closes the connection.Delete or stop the sandbox, or exec a kill in the container.
createSandbox (or a restore) throws TimeoutException although nothing is wrongBuilder.timeout applies to every request, and boots and restores can take tens of seconds on a busy machine (10–31 s were seen while testing).Leave the client-wide timeout unset and use Options.Run.timeout per command, or set it well above your slowest boot.
Kosa8Exception: capture(true) is not enough: … (0.1.0: ApiException 500: capture: no output path)The daemon needs a path to write the capture to; capture(true) has none. 0.1.1 refuses it before sending; 0.1.0 sent it and got the 500.capture("/some/folder/traffic.pcapng"): kosa8 0.9.36 writes one pcapng file at that path. On 0.1.0, create the sandbox with kosa8 sandbox create NAME --pcap FILE and drive it from Java by name.
ApiException 500: no such sandbox from startSandboxkosa8 0.9.36 answers 500, not 404, for this case.Catch ApiException rather than NotFoundException here, or check getSandbox(name) != null first.
Kosa8Exception: refusing to talk to … over plain httpA non-loopback http:// worker.Use https://; or, on a link that is already private, insecure(true) / KOSA8_INSECURE=1.
AuthException (401) from a worker, although KOSA8_TOKEN is setKOSA8_TOKEN is used only when the host came from KOSA8_HOST.Call token(…) when you call host(…).
OverlappingFileLockException from checkpoint, rewind or deleteSandbox (0.1.0 only)Two clients in one JVM, each with its own default checkpoint store, updated the file at once. Fixed in 0.1.1: stores on one path share a lock.Upgrade to 0.1.1. On 0.1.0, share one Kosa8Client, or build each with the same CheckpointStore instance.
CheckpointException: timed out after 10s waiting for …checkpoints.json.lockAnother process (often a CLI command, or a stuck program) held the checkpoint file lock for longer than the store's limit.Find the holder (lsof ~/.kosa8/checkpoints.json.lock), or allow longer: builder().checkpoints(new FileCheckpointStore(path, Duration.ofSeconds(60))).
A checkpoint taken from the CLI is missing from Java's list, or the other way round (Linux)Java's fcntl lock and the CLI's flock lock do not exclude each other on Linux, so two updates at the same instant can lose one record. On macOS they do exclude each other (tested).Do not checkpoint the same machine from the CLI and Java at the same moment on Linux, or give the SDK its own store (MemoryCheckpointStore, or FileCheckpointStore on another path).
CheckpointException: restore failed and X no longer exists … (0.1.0: "… is now stopped")The restore inside a rewind failed; on a Mac usually a locked screen. The sandbox has been deleted.Fix the cause and run the restoreSnapshot(…) call in the message. Details, including clean-up if you give up.
CheckpointException: no checkpoint "X" for sandbox "Y"No id or label matches. Labels match without regard to case; ids match exactly.sb.checkpoints() or kosa8 checkpoint ls Y.
Kosa8Exception: egressAllow already limits the network …egressAllow together with egress("any") or another non-deny value.Use one or the other.
Kosa8Exception: exec does not take env0.1.1 refuses exec with Options.Run.env; the daemon's exec has no environment (0.1.0 dropped it silently).Wrap the command: List.of("env", "K=V", "cmd"), or set the environment when starting the container with startInteractive.
Kosa8Exception: stdin of container … was already sent and is closedA second writeStdin to the same container from the same client. One body is the whole of stdin; the daemon closes it when the body ends (0.1.0 answered ok and the input was lost).Send everything in one call, or pass one InputStream that yields input over time (a PipedInputStream).
Kosa8Exception: mount "…": want host:guest or host:guest:roA mount string without exactly a host and a guest path, and optionally :ro/:rw.Fix the string. (In 0.1.0, every mount failed at the daemon with 500 mount has no guest path; upgrade.)
Kosa8Exception: mount "…": both paths must be absolute …A relative host path (mnt:/work) or a guest path without a leading /. Checked since 0.1.2.Path.of("mnt").toAbsolutePath() + ":/work".
Output callbacks see half lines, or two lines at onceCallbacks receive chunks as the daemon sends them, not lines.Buffer and split on \n yourself.
stderr appears before stdout that was printed earlierOrder is kept within a stream, not across the two.If order matters, have the command write both to one stream (2>&1).
Sandboxes pile up after crashesSandboxes outlive the JVM, and the SDK has no shutdown hook.try/finally with delete(), plus a sweep by label.

What changed in 0.1.1 and 0.1.2

0.1.1 fixes the problems found while these pages were written and tested. If you are on 0.1.0, these are the differences you will notice when you move to 0.1.1.

Area (0.1.1)0.1.00.1.1
Two clients in one JVM checkpointingOverlappingFileLockException (unchecked, not a Kosa8Exception)They queue on a shared in-process lock
Waiting for the checkpoint file lockForever10 s by default (new FileCheckpointStore(path, Duration)), then CheckpointException
Two checkpoints of one sandbox at onceCould pick the same idThe loser of the 409 steps to the next id
Options.Create.mountsEvery mount refused by the daemon (500)Works; bad strings throw before sending
Traffic capturecapture(true) got a 500capture(String path); capture(true) throws before sending
exec with envVariables silently droppedKosa8Exception
Second writeStdin to a containerAnswered ok; input never seenKosa8Exception
Failed rewind messageSaid the sandbox "is now stopped"Says it was deleted and the checkpoint is intact
Endpoint.toString()Printed the bearer tokentoken=***
Sandbox handleNo stdin, attach or framesexecFrames, startInteractive, writeStdin, attach

0.1.2

Area0.1.10.1.2
capture(String) wordingParameter hostDir; javadoc and both errors said "host directory"Parameter hostFile; the javadoc and errors say file, which is what the daemon writes
Mount pathsRelative paths sent to the daemonBoth paths must be absolute; otherwise Kosa8Exception before sending

Unchanged, because they are the daemon's behaviour: a timeout does not stop the command; a missing image or container is a StreamException; a missing sandbox on start or snapshot on restore is a 500.

Next

Java developer guide for how each feature works, and the API reference for which methods throw what. For problems with kosa8 itself rather than the SDK, see When something is wrong.