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

  1. 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.
  2. Verify disk space (df -h <cache-dir>) and inode availability if ENOSPC/EDQUOT appears.
  3. 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.
  4. 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

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


AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15). Data as JSON: /api/errors/df34daf7e0fa219c. Report an issue: GitHub.