mudler/LocalAI · error
ds4 KvCache::Save: fopen failed: %s
Error message
ds4 KvCache::Save: fopen failed: %s
What it means
C++ diagnostic from the ds4 KV-cache persister: std::fopen(path, "wb") for the cache file failed, and the message prints std::strerror(errno). The save is aborted with a plain return (no exception), so generation continues — only prefix-cache reuse for this session is lost. Path comes from Path(rendered_text), a deterministic path derived from the rendered prompt.
Source
Thrown at backend/cpp/ds4/kv_cache.cpp:180
return best_len;
}
void KvCache::Save(ds4_session *session, const std::string &rendered_text, int ctx_size) {
if (dir_.empty()) {
std::fprintf(stderr, "ds4 KvCache::Save: skipped (dir empty)\n");
return;
}
if (!session) {
std::fprintf(stderr, "ds4 KvCache::Save: skipped (session null)\n");
return;
}
std::string path = Path(rendered_text);
uint64_t payload_bytes = ds4_session_payload_bytes(session);
std::fprintf(stderr, "ds4 KvCache::Save: path=%s payload_bytes=%llu prefix_len=%zu\n",
path.c_str(), (unsigned long long)payload_bytes, rendered_text.size());
FILE *fp = std::fopen(path.c_str(), "wb");
if (!fp) {
std::fprintf(stderr, "ds4 KvCache::Save: fopen failed: %s\n", std::strerror(errno));
return;
}
char magic[4] = {'D','S','4','G'};
uint32_t version = 1;
uint32_t ctx = static_cast<uint32_t>(ctx_size);
uint32_t prefix_len = static_cast<uint32_t>(rendered_text.size());
std::fwrite(magic, 4, 1, fp);
std::fwrite(&version, 4, 1, fp);
std::fwrite(&ctx, 4, 1, fp);
std::fwrite(&prefix_len, 4, 1, fp);
std::fwrite(rendered_text.data(), prefix_len, 1, fp);
std::fwrite(&payload_bytes, 8, 1, fp);
char errbuf[256] = {0};
int rc = ds4_session_save_payload(session, fp, errbuf, sizeof(errbuf));
std::fclose(fp);
if (rc != 0) {
std::fprintf(stderr, "ds4 KvCache::Save: ds4_session_save_payload rc=%d err=%s; removing %s\n",
rc, errbuf, path.c_str());View on GitHub (pinned to 44413a9d06)
Solutions
- Check errno text in the log line: 'No such file or directory' means create the parent directory for the cache path; 'Permission denied' means chown/chmod it for the backend user.
- Verify disk space (df -h <cache-dir>) and inode availability if ENOSPC/EDQUOT appears.
- Confirm the cache path setting (or the dir derived from the rendered text path) is on a writable volume inside containers — mount an emptyDir/volume there.
- If writes are intentionally disabled, ignore the message: it is non-fatal and generation proceeds.
Example fix
# before: cache dir never created docker run localai/ds4 ... # after: ensure writable cache dir docker run -v /var/lib/localai-cache:/var/lib/localai-cache -e DS4_CACHE_DIR=/var/lib/localai-cache localai/ds4 ... mkdir -p /var/lib/localai-cache && chown localai: /var/lib/localai-cache
Defensive patterns
Strategy: validation
Validate before calling
// before KvCache::Save runs elsewhere: ensure the target dir is writable
#include <sys/stat.h>
bool ensure_cache_dir_writable(const std::string& p) {
std::string dir = p.substr(0, p.find_last_of('/'));
struct stat st;
return ::stat(dir.c_str(), &st) == 0 && S_ISDIR(st.st_mode) && ::access(dir.c_str(), W_OK) == 0;
} Prevention
- Create and chown the ds4 cache directory in your container image/unit file before first run.
- Mount a writable volume at the cache path in Kubernetes/Docker rather than relying on image layers.
- Monitor for 'fopen failed' lines: they are non-fatal but silently cost you KV prefix reuse.
When it happens
Trigger: KvCache::Save running after a prompt completes while the target directory does not exist, is not writable by the backend process user, the filesystem is full (ENOSPC), a path component is a file (ENOTDIR), or sandbox/container mounts make the cache dir read-only.
Common situations: Container images missing /tmp or model-dir cache subdirectories; ds4 running as a non-root user without write perms on the model/cache directory; disk-full nodes; SELinux/AppArmor denying writes; path template producing an unexpectedly deep directory.
Related errors
- ds4 KvCache::Save: ds4_session_save_payload rc=%d err=%s; re
- ds4-worker: missing value for %s
- ds4-worker: invalid value for %s: %s
- ds4-worker: %s
- ds4-worker: unknown option: %s
AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15).
Data as JSON: /api/errors/df34daf7e0fa219c.
Report an issue: GitHub.