{"record":{"id":"5e523f9ddb5dd2fb","repo":"commaai/openpilot","slug":"failed-to-lock-cabana-settings-s-s","errorCode":null,"errorMessage":"failed to lock Cabana settings %s: %s\n","messagePattern":"failed to lock Cabana settings (.+?): (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"openpilot/tools/cabana/settings.cc","lineNumber":59,"sourceCode":"\nnamespace {\n\nstd::filesystem::path settingsFile() {\n  return utils::configPath() / \"cabana.json\";\n}\n\nstruct LoadedSettings {\n  json11::Json::object values;\n  bool exists = false;\n  bool valid = true;\n};\n\nclass FileLock {\npublic:\n  explicit FileLock(const std::filesystem::path &path) {\n    fd = open(path.c_str(), O_CREAT | O_CLOEXEC, 0600);\n    if (fd < 0 || flock(fd, LOCK_EX) < 0) {\n      fprintf(stderr, \"failed to lock Cabana settings %s: %s\\n\", path.c_str(), strerror(errno));\n      if (fd >= 0) close(fd);\n      fd = -1;\n    }\n  }\n  ~FileLock() {\n    if (fd >= 0) close(fd);\n  }\n  bool isLocked() const { return fd >= 0; }\n\nprivate:\n  int fd = -1;\n};\n\nLoadedSettings loadSettings() {\n  std::ifstream input(settingsFile());\n  if (!input) return {};\n\n  const std::string contents{std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>()};","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/tools/cabana/settings.cc#L41-L77","documentation":"Printed by the FileLock constructor in cabana's settings.cc when open(O_CREAT) or flock(LOCK_EX) on the settings lock file fails; strerror(errno) names the cause. FileLock guards settings.json against concurrent writers (two cabana instances). On failure it degrades: fd is set to -1, isLocked() returns false, and the caller decides whether to proceed — so this is a warning-level diagnostic, though losing the lock means settings writes can race.","triggerScenarios":"Two cabana instances starting simultaneously; the settings directory (usually ~/.comma/cabana or the configured data dir) being read-only, full, or owned by another user; or a filesystem without flock support (some network mounts). open failing (fd<0) or flock failing both land here.","commonSituations":"Running cabana as a different user than the one who owns the config dir, a full disk, NFS/overlay filesystems, or genuinely launching a second cabana while the first is writing settings.","solutions":["Check the printed path and errno string: 'Permission denied' -> fix ownership/permissions of the settings dir; 'Read-only file system' -> pick a writable --data_dir.","Close other running cabana instances before starting a new one if you need the lock honored.","Free disk space if ENOSPC is the reported errno.","If on an exotic FS lacking flock, point cabana's settings/data dir at a local filesystem."],"exampleFix":"# before\ncabana   # settings dir owned by root -> 'failed to lock ... Permission denied'\n\n# after\nsudo chown -R $USER ~/.comma\ncabana","handlingStrategy":"validation","validationCode":"import os, fcntl\nlock_path = os.path.expanduser('~/.comma/cabana/settings.lock')\nos.makedirs(os.path.dirname(lock_path), exist_ok=True)\nfd = os.open(lock_path, os.O_CREAT, 0o600)\ntry:\n    fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)\n    locked = True\nexcept OSError:\n    locked = False  # another instance holds it; skip settings writes","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure the settings directory is writable and owned by the invoking user.","Avoid running two cabana instances sharing one data dir.","Keep settings on a local filesystem that supports flock."],"tags":["cabana","file-locking","settings","filesystem","openpilot"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}