JuliusBrussee/caveman · error
native session key mkdir: %w
Error message
native session key mkdir: %w
What it means
LoadOrCreateSessionKey creates <home>/runtime with mode 0700 before writing the shared HMAC session key. This error means MkdirAll failed — typically a permission problem on the parent directory, a read-only filesystem, or a path component that exists as a file instead of a directory.
Source
Thrown at proxy/internal/nativeruntime/marker.go:26
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
)
const sessionKeyBytes = 32
var markerPattern = regexp.MustCompile(`\[\[caveman-session-v1 sid="([A-Za-z0-9_-]{1,384})" sig="([0-9a-f]{64})"\]\]`)
// LoadOrCreateSessionKey returns one user-only HMAC key shared by CLI adapters
// and local proxy. O_EXCL makes concurrent first startup converge on one key.
func LoadOrCreateSessionKey(home string) ([]byte, error) {
dir := filepath.Join(home, "runtime")
if err := os.MkdirAll(dir, 0o700); err != nil {
return nil, fmt.Errorf("native session key mkdir: %w", err)
}
if err := os.Chmod(dir, 0o700); err != nil {
return nil, fmt.Errorf("native session key chmod dir: %w", err)
}
path := filepath.Join(dir, "session.key")
key := make([]byte, sessionKeyBytes)
if _, err := rand.Read(key); err != nil {
return nil, fmt.Errorf("native session key random: %w", err)
}
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600)
if err == nil {
if _, writeErr := file.Write(key); writeErr != nil {
_ = file.Close()
_ = os.Remove(path)
return nil, fmt.Errorf("native session key write: %w", writeErr)
}
if syncErr := file.Sync(); syncErr != nil {
_ = file.Close()View on GitHub (pinned to 27d5a3981a)
Solutions
- Check the underlying error: 'not a directory' means a file occupies <home>/runtime — remove or rename it
- 'permission denied' means fix ownership/permissions: chown the home dir to the running user, or chmod to allow writes
- Set HOME (or the equivalent home argument) to a writable per-user directory
- On read-only filesystems, point home at a writable volume
Example fix
# before $ ls -la ~/.caveman runtime # a regular file -> Error[1066] # after $ rm ~/.caveman/runtime && mkdir -p ~/.caveman/runtime && chmod 700 ~/.caveman/runtime
Defensive patterns
Strategy: validation
Validate before calling
func homeWritable(home string) error {
fi, err := os.Stat(filepath.Join(home, "runtime"))
if err == nil && !fi.IsDir() {
return fmt.Errorf("%s exists but is not a directory", fi.Name())
}
if err != nil && !os.IsNotExist(err) {
return err
}
return nil
} Prevention
- Run the proxy and CLI as one user with an exclusive HOME
- Pre-create <home>/runtime with 0700 in provisioning
- Never let config management place a file named 'runtime' under home
When it happens
Trigger: home points at a directory the process cannot write (owned by root, mode 0755 with different user); <home>/runtime already exists as a regular file; running with HOME unset so home resolves to an invalid path; container with a read-only volume mounted at home.
Common situations: Running the proxy/CLI under a service user whose HOME differs from expectations; stale 'runtime' file left by a bad install; immutable container filesystems.
Related errors
- native session key chmod dir: %w
- native session key create: %w
- native session key write: %w
- native session key sync: %w
- native session key close: %w
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/315a9e72204788e9.
Report an issue: GitHub.