Troubleshooting¶
argv must not be empty¶
ExecSpec.argv and SpawnSpec.argv must include the executable as the first element.
ExecSpec(argv = listOf("git", "status"))
kotlin-exec does not parse shell command strings. Pass arguments as separate list elements, or
invoke a shell explicitly when shell parsing is required.
Command Works In A Shell But Not Through kotlin-exec¶
Shells expand globs, variables, aliases, functions, and redirections. kotlin-exec passes argv
directly to the process launcher.
If shell behavior is intentional, use:
ExecSpec.tooling(listOf("sh", "-c", "printf '%s\\n' *.kt"))
On Windows, use the appropriate shell such as cmd /c or PowerShell.
Missing PATH Or Environment Variables¶
Check the selected EnvPolicy.
EnvPolicy.ClearAndSet uses exactly the supplied map. If the command relies on PATH, provide it
explicitly or use EnvPolicy.Hermetic, which installs a minimal launch environment before applying
your variables. See the Environment Policies section of the user guide for the exact Unix and
Windows variables supplied by EnvPolicy.Hermetic.
Output Is Truncated¶
Captured output is intentionally bounded. Inspect:
ExecResult.Captured.truncatedExecResult.Captured.bytesReadExecResult.stdoutStatsExecResult.stderrStats
Increase maxBytes or use SinkSpec.File for large output.
Process Is Killed On Timeout¶
This is expected for managed execution. Exec.exec and Exec.execBlocking own the child lifecycle,
so timeout is destructive.
Use Exec.spawn or Exec.spawnBlocking when timeout should not kill the process.
Spawn Does Not Capture Output¶
Spawn currently supports inherit, discard, and file redirects. It does not provide in-memory capture because the process continues after the call returns and output ownership remains open-ended.
Use managed exec for captured foreground runs, or redirect spawn output to files.
Blocking Execution Fails With Virtual Thread Requirement¶
VirtualThreadsPolicy.Require needs a JDK with virtual-thread support. Use
VirtualThreadsPolicy.Prefer to use virtual threads when available and fall back otherwise.
Stream Callback Sees Mutating Buffers¶
SinkSpec.Stream passes an internal reusable buffer by default. Set copyChunks = true if the
callback stores the byte array after returning.
Output Limit Kills The Process¶
This happens when a sink uses OverflowPolicy.KillProcess. Use DrainAndTruncate when the process
should continue and only retention should be bounded.