{"record":{"id":"47bea9251a1cf351","repo":"commaai/openpilot","slug":"failed-to-create-temporary-cabana-settings-s-s","errorCode":null,"errorMessage":"failed to create temporary Cabana settings %s: %s\n","messagePattern":"failed to create temporary Cabana settings (.+?): (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"openpilot/tools/cabana/settings.cc","lineNumber":115,"sourceCode":"\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();\n  const std::string contents = json11::Json(settings_json).dump();\n  std::string temporary_path = path.string() + \".tmp.XXXXXX\";\n  int fd = mkstemp(temporary_path.data());\n  if (fd < 0) {\n    fprintf(stderr, \"failed to create temporary Cabana settings %s: %s\\n\", temporary_path.c_str(), strerror(errno));\n    return false;\n  }\n\n  bool success = writeAll(fd, contents) && fsync(fd) == 0;\n  if (close(fd) < 0) success = false;\n  if (success && rename(temporary_path.c_str(), path.c_str()) < 0) success = false;\n\n  if (success) {\n    int dir_fd = open(path.parent_path().c_str(), O_RDONLY | O_CLOEXEC);\n    success = dir_fd >= 0 && fsync(dir_fd) == 0;\n    if (dir_fd >= 0 && close(dir_fd) < 0) success = false;\n  }\n\n  if (!success) {\n    const int saved_errno = errno;\n    unlink(temporary_path.c_str());\n    fprintf(stderr, \"failed to save Cabana settings to %s: %s\\n\", path.c_str(), strerror(saved_errno));\n  }","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/tools/cabana/settings.cc#L97-L133","documentation":"Emitted by saveSettings() in tools/cabana/settings.cc when mkstemp() on '<cabana.json>.tmp.XXXXXX' returns a negative fd. Save uses a write-to-temp + rename pattern for atomicity; this message means the temporary file itself could not be created, so nothing was written and saveSettings returns false.","triggerScenarios":"saveSettings() reaching mkstemp(path.string() + \".tmp.XXXXXX\") when the config directory does not exist, is not writable by the current user, the filesystem is full (no inode/space), or a filesystem error like EDQUOT/EROFS occurs. Note the string passed to mkstemp must be modifiable — it is, via .data() on a std::string — so the failure is environmental, not an API misuse.","commonSituations":"ensureSettingsDirectory() failed earlier (see error 141) but save was attempted anyway; running cabana under a user without write access to ~/.comma; disk-full on a long session that saves settings on every change; SELinux/AppArmor denying writes to the config dir.","solutions":["Confirm the config directory exists and is writable: `mkdir -p <configPath> && touch <configPath>/cabana.json.tmp.test && rm <configPath>/cabana.json.tmp.test`.","Free disk space / inodes if the message's strerror says 'No space left on device'.","Run cabana as the user who owns the config dir, or fix ownership.","Handle the return value: saveSettings() returning false is expected to be non-fatal; settings just won't persist this session."],"exampleFix":"// before\n// stderr: failed to create temporary Cabana settings /home/user/.comma/cabana.json.tmp.AbC123: Permission denied\n\n# after (fix the environment)\nsudo chown -R $USER:$USER /home/user/.comma\ncabana  # settings save succeeds","handlingStrategy":"validation","validationCode":"// Before triggering a save (e.g. before relying on settings persistence),\n// confirm mkstemp can create a temp file in the config dir:\nbool canCreateTempIn(const std::filesystem::path &dir) {\n  std::string tmpl = (dir / \"cabana.tmp.XXXXXX\").string();\n  int fd = mkstemp(tmpl.data());\n  if (fd < 0) return false;\n  unlink(tmpl.c_str());\n  close(fd);\n  return true;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the config directory writable and non-full; cabana saves on every settings change, so free disk alarms protect settings too.","Call ensureSettingsDirectory() (or verify it succeeded) before relying on saves.","Avoid running two cabana instances with different privilege levels against one config dir."],"tags":["cabana","settings","mkstemp","filesystem","permissions","atomic-write"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}