{"record":{"id":"df34daf7e0fa219c","repo":"mudler/LocalAI","slug":"ds4-kvcache-save-fopen-failed-s","errorCode":null,"errorMessage":"ds4 KvCache::Save: fopen failed: %s\n","messagePattern":"ds4 KvCache::Save: fopen failed: (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/cpp/ds4/kv_cache.cpp","lineNumber":180,"sourceCode":"    return best_len;\n}\n\nvoid KvCache::Save(ds4_session *session, const std::string &rendered_text, int ctx_size) {\n    if (dir_.empty()) {\n        std::fprintf(stderr, \"ds4 KvCache::Save: skipped (dir empty)\\n\");\n        return;\n    }\n    if (!session) {\n        std::fprintf(stderr, \"ds4 KvCache::Save: skipped (session null)\\n\");\n        return;\n    }\n    std::string path = Path(rendered_text);\n    uint64_t payload_bytes = ds4_session_payload_bytes(session);\n    std::fprintf(stderr, \"ds4 KvCache::Save: path=%s payload_bytes=%llu prefix_len=%zu\\n\",\n                 path.c_str(), (unsigned long long)payload_bytes, rendered_text.size());\n    FILE *fp = std::fopen(path.c_str(), \"wb\");\n    if (!fp) {\n        std::fprintf(stderr, \"ds4 KvCache::Save: fopen failed: %s\\n\", std::strerror(errno));\n        return;\n    }\n    char magic[4] = {'D','S','4','G'};\n    uint32_t version = 1;\n    uint32_t ctx = static_cast<uint32_t>(ctx_size);\n    uint32_t prefix_len = static_cast<uint32_t>(rendered_text.size());\n    std::fwrite(magic, 4, 1, fp);\n    std::fwrite(&version, 4, 1, fp);\n    std::fwrite(&ctx, 4, 1, fp);\n    std::fwrite(&prefix_len, 4, 1, fp);\n    std::fwrite(rendered_text.data(), prefix_len, 1, fp);\n    std::fwrite(&payload_bytes, 8, 1, fp);\n    char errbuf[256] = {0};\n    int rc = ds4_session_save_payload(session, fp, errbuf, sizeof(errbuf));\n    std::fclose(fp);\n    if (rc != 0) {\n        std::fprintf(stderr, \"ds4 KvCache::Save: ds4_session_save_payload rc=%d err=%s; removing %s\\n\",\n                     rc, errbuf, path.c_str());","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/backend/cpp/ds4/kv_cache.cpp#L162-L198","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before: cache dir never created\n docker run localai/ds4 ...\n\n# after: ensure writable cache dir\n docker run -v /var/lib/localai-cache:/var/lib/localai-cache -e DS4_CACHE_DIR=/var/lib/localai-cache localai/ds4 ...\n mkdir -p /var/lib/localai-cache && chown localai: /var/lib/localai-cache","handlingStrategy":"validation","validationCode":"// before KvCache::Save runs elsewhere: ensure the target dir is writable\n#include <sys/stat.h>\nbool ensure_cache_dir_writable(const std::string& p) {\n    std::string dir = p.substr(0, p.find_last_of('/'));\n    struct stat st;\n    return ::stat(dir.c_str(), &st) == 0 && S_ISDIR(st.st_mode) && ::access(dir.c_str(), W_OK) == 0;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["cpp","ds4","kv-cache","filesystem","persistence"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}