{"record":{"id":"d01a53d0d66f72b9","repo":"commaai/openpilot","slug":"failed-to-create-cabana-settings-directory-s-s","errorCode":null,"errorMessage":"failed to create Cabana settings directory %s: %s\n","messagePattern":"failed to create Cabana settings directory (.+?): (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"openpilot/tools/cabana/settings.cc","lineNumber":92,"sourceCode":"  std::ifstream input(settingsFile());\n  if (!input) return {};\n\n  const std::string contents{std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>()};\n  std::string error;\n  auto settings_json = json11::Json::parse(contents, error);\n  if (!error.empty() || !settings_json.is_object()) {\n    fprintf(stderr, \"failed to read Cabana settings %s%s%s\\n\", settingsFile().c_str(), error.empty() ? \"\" : \": \", error.c_str());\n    return {.exists = true, .valid = false};\n  }\n  return {.values = settings_json.object_items(), .exists = true};\n}\n\nbool ensureSettingsDirectory() {\n  const auto path = settingsFile();\n  std::error_code error;\n  std::filesystem::create_directories(path.parent_path(), error);\n  if (error) {\n    fprintf(stderr, \"failed to create Cabana settings directory %s: %s\\n\", path.parent_path().c_str(), error.message().c_str());\n    return false;\n  }\n  return true;\n}\n\nbool writeAll(int fd, const std::string &data) {\n  size_t written = 0;\n  while (written < data.size()) {\n    ssize_t result = write(fd, data.data() + written, data.size() - written);\n    if (result < 0 && errno == EINTR) continue;\n    if (result <= 0) return false;\n    written += result;\n  }\n  return true;\n}\n\nbool saveSettings(const json11::Json::object &settings_json) {\n  const auto path = settingsFile();","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/tools/cabana/settings.cc#L74-L110","documentation":"Emitted by ensureSettingsDirectory() in tools/cabana/settings.cc when std::filesystem::create_directories on the parent of the settings file (utils::configPath()) reports an error via the std::error_code overload. This means Cabana cannot even create the directory that would hold cabana.json, so settings persistence will fail. The function returns false so callers know saving is unavailable.","triggerScenarios":"Calling ensureSettingsDirectory() (directly or via saveSettings) when the config directory path cannot be created: a component of utils::configPath() exists as a regular file, the user lacks write permission on the parent, the path is on a read-only mount, or (rarely) the path exceeds NAME_MAX/PATH_MAX. The error_code out-param is non-zero after create_directories(path.parent_path(), error).","commonSituations":"Running Cabana as a different user than the one owning ~/.comma; HOME unset or pointing somewhere non-writable (CI containers, root shells); a stale regular file sitting where the directory should be; read-only NFS/container mounts.","solutions":["Inspect the printed path and errno message; usually fix with `mkdir -p <configPath>` as the right user or `rm` the regular file blocking the directory.","Ensure HOME is set and writable for the user running cabana (the message text names the exact parent path).","Check permissions/ownership: `chown -R $USER <configPath parent>` or chmod u+w.","If intentional (read-only rootfs), ignore — Cabana runs with default settings, it just cannot persist them."],"exampleFix":"# before: message says e.g. 'failed to create Cabana settings directory /home/user/.comma: Not a directory'\nls -la /home/user/.comma   # a regular file is squatting on the path\nrm /home/user/.comma\n# after: directory is created on next start, message gone","handlingStrategy":"validation","validationCode":"// Pre-check directory creatability before cabana tries to save settings:\nbool configDirUsable(const std::filesystem::path &dir) {\n  std::error_code ec;\n  std::filesystem::create_directories(dir, ec);\n  if (ec) return false;\n  auto probe = dir / \".write-probe\";\n  std::ofstream t(probe);\n  bool ok = t.good();\n  t.close();\n  std::filesystem::remove(probe);\n  return ok;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run cabana under the user that owns the config directory (~/.comma).","In containers/CI, set HOME to a writable path or mount a writable volume at the config dir.","Don't place regular files where the config directory path is expected."],"tags":["cabana","settings","filesystem","permissions","directory"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}