{"record":{"id":"121ba8a331892a8a","repo":"Hmbown/CodeWhale","slug":"nsposixerrordomain-errno","errorCode":null,"errorMessage":"NSPOSIXErrorDomain errno","messagePattern":"NSPOSIXErrorDomain errno","errorType":"error_code","errorClass":"NSError(NSPOSIXErrorDomain)","httpStatus":null,"severity":"error","filePath":"pet/swift/PetHabitatStore.swift","lineNumber":92,"sourceCode":"                let written = Darwin.write(file, bytes.baseAddress!.advanced(by: offset), bytes.count - offset)\n                if written < 0 && errno == EINTR { continue }\n                guard written > 0 else { throw Self.ioError() }\n                offset += written\n            }\n        }\n        guard fsync(file) == 0 else { throw Self.ioError() }\n        if immutable {\n            if linkat(directory, temporary, directory, name, 0) != 0 {\n                guard errno == EEXIST, try read(name: name, limit: 64 * 1024 * 1024) == value else { throw Self.ioError() }\n            }\n        } else if renameat(directory, temporary, directory, name) != 0 { throw Self.ioError() }\n    }\n\n    private func coordinated<T>(_ action: () throws -> T) throws -> T {\n        guard flock(lock, LOCK_EX | LOCK_NB) == 0 else { throw Self.ioError() }\n        defer { flock(lock, LOCK_UN) }\n        let current = openat(directory, lockName, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC)\n        guard current >= 0 else { throw Self.ioError() }\n        defer { close(current) }\n        let original = try Self.regular(lock), now = try Self.regular(current)\n        guard original.st_dev == now.st_dev && original.st_ino == now.st_ino else { throw Self.invalid(\"The habitat writer lock was replaced.\") }\n        return try action()\n    }\n\n    private func read(name key: String? = nil, limit: Int = PetHabitatStore.limit) throws -> Data? {\n        let file = openat(directory, key ?? name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC)\n        if file < 0 && errno == ENOENT { return nil }\n        guard file >= 0 else { throw Self.ioError() }\n        defer { close(file) }\n        let info = try Self.regular(file)\n        guard info.st_size >= 0 && info.st_size <= limit else { throw Self.invalid(\"The saved habitat exceeds 8 MiB.\") }\n        var value = Data(), buffer = [UInt8](repeating: 0, count: 16_384)\n        while true {\n            let count = Darwin.read(file, &buffer, min(buffer.count, limit + 1 - value.count))\n            if count < 0 && errno == EINTR { continue }\n            guard count >= 0 else { throw Self.ioError() }","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/swift/PetHabitatStore.swift#L74-L110","documentation":"At PetHabitatStore.swift:92, coordinated(_:) throws Self.ioError() — an NSPOSIXErrorDomain error carrying the live errno — when openat(directory, lockName, O_RDONLY|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC) fails to reopen the lock file. ENOENT means the lock file was deleted or renamed after the store was initialized; other errno values indicate permission or descriptor problems. The open-with-O_NOFOLLOW validation step exists to detect lock-file tampering before running the critical section.","triggerScenarios":"load() or save() when the `<source>.lock` file has been removed from the habitat directory since PetHabitatStore.init; EACCES/EPERM after directory permissions were tightened; EMFILE when the process has exhausted its file-descriptor limit.","commonSituations":"A cleanup script or the user manually deletes lock files inside the app-support directory; a sync service (iCloud Drive, Dropbox) replaces or removes the directory contents; too many open files after a leak elsewhere.","solutions":["Recreate the store: re-run PetHabitatStore.init, which re-creates the missing `<source>.lock` file (O_CREAT) with 0600 permissions.","Restore the habitat directory contents — stop any sync tool from managing that folder or exclude it from syncing.","Check fd exhaustion with `lsof -p <pid> | wc -l` against the RLIMIT_NOFILE and fix the descriptor leak.","Verify directory permissions remain 0700 and are owned by the current user."],"exampleFix":"// before: keep using a store whose lock file vanished\ntry store.save(payload)\n\n// after: rebuild the store when the lock file is gone\ndo { try store.save(payload) }\ncatch let e as NSError where e.domain == NSPOSIXErrorDomain && e.code == ENOENT {\n    store = try PetHabitatStore(directory: habitatURL, source: source)\n    try store.save(payload)\n}","handlingStrategy":"fallback","validationCode":"// Verify the lock file still exists before operating\nFileManager.default.fileExists(atPath: url.appendingPathComponent(source + \".lock\").path)","typeGuard":"func isLockFileMissing(_ e: Error) -> Bool {\n    let n = e as NSError\n    return n.domain == NSPOSIXErrorDomain && n.code == ENOENT\n}","tryCatchPattern":"do { try store.save(payload) }\ncatch let e as NSError where e.domain == NSPOSIXErrorDomain && e.code == ENOENT {\n    store = try PetHabitatStore(directory: url, source: source) // recreate lock\n    try store.save(payload)\n}","preventionTips":["Exclude the habitat directory from sync/backup tools that delete lock files.","Rebuild the store instead of reusing it after external directory changes.","Keep the directory permissions at 0700 and owned by the app user."],"tags":["file-locking","posix","swift","file-not-found"],"backgroundTag":"file-not-found","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}