{
 "number": 35676,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35676",
 "title": "util: Abort in CheckDiskSpace/FlatFileSeq::Open on rare exceptions",
 "author": "maflcko",
 "author_association": "MEMBER",
 "created_at": "2026-07-07T12:29:12Z",
 "updated_at": "2026-09-13T04:53:10Z",
 "age_days": 72,
 "draft": false,
 "labels": [
  "Utils/log/libs"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "fac9306686142f65cef2824088f81efc8884aacb",
 "head_ref": "2607-io-errors",
 "head_repo": "maflcko/bitcoin-core",
 "head_history": [
  {
   "t": "2026-07-07T12:47:05Z",
   "sha": "fa872a590e1f1f658fc56034cf98befea05d1003"
  },
  {
   "t": "2026-07-07T13:51:01Z",
   "sha": "fae76cf3bb04a3f80deb7579eb0d0b7235a7e39f"
  },
  {
   "t": "2026-07-07T14:33:02Z",
   "sha": "fa12aabc66ef5e7d2ab2b8062fa0580cff54f8b5"
  },
  {
   "t": "2026-07-09T13:29:32Z",
   "sha": "fad3a5324b4d9d105decb234b88eb9947405f608"
  },
  {
   "t": "2026-07-09T13:53:37Z",
   "sha": "fac988c3b6fb0eea77ae81611c406365c19604df"
  },
  {
   "t": "2026-07-09T13:58:03Z",
   "sha": "fac9306686142f65cef2824088f81efc8884aacb"
  }
 ],
 "additions": 155,
 "deletions": 3,
 "changed_files": 6,
 "commit_count": 2,
 "size_bucket": "M",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "furszy",
      "url": "https://github.com/bitcoin/bitcoin/pull/35676#issuecomment-4904633140"
     },
     {
      "login": "l0rinc",
      "url": "https://github.com/bitcoin/bitcoin/pull/35676#issuecomment-4909442592"
     }
    ]
   },
   "conflicts": [
    {
     "number": 35003,
     "title": "validation: improve block data I/O error handling in P2P paths",
     "author": "furszy"
    },
    {
     "number": 34132,
     "title": "coins, dbwrapper: remove error catcher, make point-read failures fatal",
     "author": "l0rinc"
    }
   ]
  }
 },
 "acks_parsed": {
  "furszy": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-07-07T14:00:00Z",
   "stale": false
  },
  "l0rinc": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-07-07T22:02:02Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "furszy",
   "josibake",
   "l0rinc",
   "optout21",
   "sedited"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-07-15T15:03:41Z",
  "last_reviewer_activity": "2026-07-14T15:26:55Z",
  "last_reviewer": "sedited",
  "author_silent_days": 64,
  "waiting_on_author_days": 0,
  "days_since_update": 4
 },
 "refs": {
  "mentioned": [
   34897,
   35003
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 34897,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-07-09",
    "title": "indexes: Don't commit ahead of the flushed chainstate"
   },
   {
    "number": 35003,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "validation: improve block data I/O error handling in P2P paths"
   }
  ],
  "conflicts": [
   35003,
   34132
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/flatfile.cpp",
  "src/util/fs_helpers.cpp"
 ],
 "body": "Currently, exceptions from `CheckDiskSpace` calls in the scheduler thread (e.g. from events for `blockfilterindex` or the scheduled disk space check) are not caught, leading to a program termination:\n\n```\nterminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'\n  what():  filesystem error: cannot get free space: No such file or directory [/tmp/bitcoin_func_test_1xy14g2w/node0/regtest/indexes/blockfilter/basic]\n```\n\nImmediate termination is fine, because those exceptions are unexpected, but it could make sense to be consistent and treat all paths equally and abort the program.\n\nAborting the program here is fine, because the exceptions happen so rarely, that they are similar in frequency to other unclean shutdown reasons. The exceptions basically can only happen when the user unplugs the external USB drive, but this sounds as likely as an OOM kill (or other kill of the program), which also results in an abort.",
 "commits": [
  {
   "sha": "faab1e4d3bd26d235f09d478988b9f37cf822d63",
   "date": "2026-07-09T13:51:36Z",
   "message": "test: Check handling of I/O erros from CheckDiskSpace (via Allocate)"
  },
  {
   "sha": "fac9306686142f65cef2824088f81efc8884aacb",
   "date": "2026-07-09T13:57:57Z",
   "message": "util: Abort in CheckDiskSpace on rare exceptions"
  }
 ],
 "timeline": [
  {
   "t": "2026-07-07T12:47:05Z",
   "kind": "force_push",
   "who": "maflcko",
   "commit": "fa872a590e1f1f658fc56034cf98befea05d1003"
  },
  {
   "t": "2026-07-07T13:51:01Z",
   "kind": "force_push",
   "who": "maflcko",
   "commit": "fae76cf3bb04a3f80deb7579eb0d0b7235a7e39f"
  },
  {
   "t": "2026-07-07T14:00:00Z",
   "kind": "comment",
   "who": "furszy",
   "assoc": "MEMBER",
   "text": "Concept ACK, related to https://github.com/bitcoin/bitcoin/pull/35003#discussion_r3424554696"
  },
  {
   "t": "2026-07-07T14:33:02Z",
   "kind": "force_push",
   "who": "maflcko",
   "commit": "fa12aabc66ef5e7d2ab2b8062fa0580cff54f8b5"
  },
  {
   "t": "2026-07-07T14:39:46Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThx for the context. Reminded me that adding a test for the scheduler check is trivial, so I did that as well."
  },
  {
   "t": "2026-07-07T14:45:02Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "I'm not sure about this change, and the functional test is basically illustrating my hesitation. This now clobbers a potential existence, or permissions error into a disk space fault. The goal in my mind should be to make diagnostics easier. If we really want to clobber all error categories and report which function failed, rather than why something went wrong, shouldn't we at least be logging some detail? I'm starting to think we have these concepts backwards, maybe crashing is actually preferable in some places."
  },
  {
   "t": "2026-07-07T14:47:48Z",
   "kind": "review_comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "path": "src/util/fs_helpers.cpp",
   "commit": "fac9306686142f65cef2824088f81efc8884aacb",
   "in_reply_to": null,
   "text": "This now conflates a program logic question, \"Is there enough disk space\", with an actual programming bug, e.g., not satisfying the function's preconditions by passing in a directory that doesn't exist. I understand the desire for consistency, but I don't think this is the way to do it."
  },
  {
   "t": "2026-07-07T14:52:31Z",
   "kind": "comment",
   "who": "furszy",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\n+1, it would be nice to log what caused the error at least."
  },
  {
   "t": "2026-07-07T15:48:27Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI am not opposed to crashing. I just wonder which errors should lead to a crash and which errors should lead to a fatal shutdown (with a best-effort flush). I can see that trying to gracefully try to flush in case of an out-of-space could make sense to avoid data loss on a best-effort basis. I can also see that crashing in case of hardware or software corruption is preferable.\n\nFor me, it just seems odd that the same i/o exception can sometimes be caught and be handled, and other times it leads to a terminate. Maybe this is just me, and if other reviewers are fine with that and think that those different handling paths are irrelevant or preferable, then we can probably close this (and other such cleanups)."
  },
  {
   "t": "2026-07-07T22:02:02Z",
   "kind": "comment",
   "who": "l0rinc",
   "assoc": "MEMBER",
   "text": "Concept ACK"
  },
  {
   "t": "2026-07-08T05:23:45Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "To expand my earlier comment: If we don't care about those types of exceptions and think that crashing is preferable, the two functions should be marked `noexcept`. This also follows the pattern of other throwing functions that are marked so: `GenerateRandomGarbage() noexcept`, `SQLiteDatabase::Cleanup() noexcept`, ..."
  },
  {
   "t": "2026-07-09T12:51:00Z",
   "kind": "comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI think this is one of the strengths of exceptions: its impossible to ignore them, unlike error codes. So I think the correct thing is allow them to propagate up to the appropriate layer, where they can be handled. The question I'd pose instead is \"what is the appropriate layer,\" or \"are there multiple layers.\" If we can't find a layer to handle an exception, having it terminate seems the safest, no?"
  },
  {
   "t": "2026-07-09T13:29:32Z",
   "kind": "force_push",
   "who": "maflcko",
   "commit": "fad3a5324b4d9d105decb234b88eb9947405f608"
  },
  {
   "t": "2026-07-09T13:34:21Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI am not sure if it is impossible to ignore exceptions. There are several catch-all in the codebase, which lead to exceptions sometimes being silently ignored, and other times lead to an abort if they are not caught, and it is not clear from a quick glance which code outcome will be hit.\n\nIf we think that a terminate is fine here, I think then it is fine to do it consistently. The patch would be trivial, and I've pushed it.\n\nIf we think a terminate is not fine here, and it should be a fatal shutdown, I think all possible paths should be fixed and handled and properly lead to a fatal shutdown."
  },
  {
   "t": "2026-07-09T13:53:37Z",
   "kind": "force_push",
   "who": "maflcko",
   "commit": "fac988c3b6fb0eea77ae81611c406365c19604df"
  },
  {
   "t": "2026-07-09T13:58:03Z",
   "kind": "force_push",
   "who": "maflcko",
   "commit": "fac9306686142f65cef2824088f81efc8884aacb"
  },
  {
   "t": "2026-07-09T14:03:08Z",
   "kind": "comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThat's a different problem of catching the exception and doing nothing with it. My original comment was referring to impossible to ignore _uncaught_ exceptions (perhaps poorly worded).\n\nWith your most recent push, I still think this PR is repeating the same bad pattern of having a policy decision being made in a low level primitive. The function should do what its asked (check the disk space) and give an exception back to the caller if it cannot complete the task. The caller then decides to either do something with the exception, or just let it propagate up if they don't have enough information, context, authority etc to do something.\n\nIf we keep following this pattern, over time this allows us to have all of our error handling logic and logging consolidated into boundaries where its much easier to reason about whats going on.\n\n[quoted text omitted]\nNot disagreeing with this, I just don't think this is the right way to enforce consistency. I'd rather we get rid of the do nothing catch alls, letting any unhandled exception terminate for free. For anything that can be handled, catch it at the appropriate layer and take a policy action owned by that boundary."
  },
  {
   "t": "2026-07-10T11:51:41Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/util/fs_helpers.cpp",
   "commit": "fac9306686142f65cef2824088f81efc8884aacb",
   "in_reply_to": 3537406216,
   "text": "(solving for now, because this comment applies to prior code that was `return false;` here)."
  },
  {
   "t": "2026-07-10T14:02:02Z",
   "kind": "review_comment",
   "who": "furszy",
   "assoc": "MEMBER",
   "path": "src/flatfile.cpp",
   "commit": "fac9306686142f65cef2824088f81efc8884aacb",
   "in_reply_to": null,
   "text": "I don't think a low-level unclean shutdown is the right approach. An error accessing an index directory or another unrelated file shouldn't prevent the chain or wallet from attempting to flush their state to disk. They could be living in a different storage location."
  },
  {
   "t": "2026-07-10T14:18:06Z",
   "kind": "comment",
   "who": "furszy",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI would be careful with this sentence, as it is a strong general statement. At the p2p layer, this could result in a remotely triggerable abortion. We cannot know where or how the code may be used in the future, but we can do the work to provide a safe interface that prevents such issues. I would take the safer approach and handle exceptions consistently."
  },
  {
   "t": "2026-07-10T14:18:27Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/flatfile.cpp",
   "commit": "fac9306686142f65cef2824088f81efc8884aacb",
   "in_reply_to": 3559484504,
   "text": "Aborting the program here is fine, because the exceptions happen so rarely, that they are similar in frequency to other unclean shutdown reasons. The exceptions basically can only happen when the user unplugs the external USB drive, but this sounds as likely as an OOM kill (or other kill of the program), which also results in an abort.\n\nUnclean shut-downs happen (and they should be supported), see e.g. https://github.com/bitcoin/bitcoin/issues/33208.\n\nIt is impossible to avoid all unclean shutdowns. There can always be a power outage, an overheated CPU, a kernel panic, an OOM, an assertion failure, a typo in the pid of `kill -9`, etc. So I think it is fine to add one more rare thing to the list here.\n\nAlso, this commit is trivial to revert, if another approach is taken, but such an approach will likely have to touch the whole codebase to bubble up the error/exception and handle (or not handle) it."
  },
  {
   "t": "2026-07-10T14:49:49Z",
   "kind": "review_comment",
   "who": "furszy",
   "assoc": "MEMBER",
   "path": "src/flatfile.cpp",
   "commit": "fac9306686142f65cef2824088f81efc8884aacb",
   "in_reply_to": 3559484504,
   "text": "[quoted text omitted]\n\nDownloading + validating the chain is expensive, and ending up with a wallet in an inconsistent state due to an unclean shutdown is dangerous. They could easily be residing in different storage devices, we do have options for it. Attempting a clean shutdown, even during rare errors like this one, seems the safest approach for soft that is responsible of storing users' funds. At least that is my view.\n\n[quoted text omitted]\nThat shouldn't be the case anymore, we just merged #34897 which avoids reaching the situation of persisting a locator from a block that hasn't been flushed to disk yet.\n\n[quoted text omitted]\nI don't think this is a strong argument, I could have used the same argument to answer to your message https://github.com/bitcoin/bitcoin/pull/35003#issuecomment-4926909310 too? at least #35003 introduces coverage to all the affected areas while this one doesn't."
  },
  {
   "t": "2026-07-10T15:14:26Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/flatfile.cpp",
   "commit": "fac9306686142f65cef2824088f81efc8884aacb",
   "in_reply_to": 3559484504,
   "text": "[quoted text omitted]\n\nI don't think this abort will delete any previously downloaded and flushed block files, so no re-download is needed. Also, validation progress is flushed regularly during IBD, catching up a few minutes after a rare unclean shutdown (for whatever reason) should be fine.\n\n[quoted text omitted]\nYes, that is the point. I just wanted to show an example that unclean shutdowns are not recommended, but supported. That is, if a bug is hit after restart after an unclean shutdown, it is a bug that should be fixed. (And such bugs have been fixed in the past.)\n\n[quoted text omitted]\nHappy to cherry-pick the test over here. It should be trivial. Otherwise, i think the downsides of 35003 in its current form are:\n\n* 35003 doesn't deal with `CheckDiskSpace`, so it is incomplete and a separate pull will be needed anyway\n* 35003 doesn't deal with p2p logic, so the node may keep running and may leave peers connected and silently not reply to them\n* 35003 doesn't deal with indexes: It silently returns that a blockchain transaction does not exist in the chain, when it *does* exist in the chain.\n\nSo all of those will need another pull to take care of. My main concern is that 35003 will be merged and the stuff isn't followed-up on. My view is that in this area, we need to fix all issues (or at least agree on how to fix them) without regressing in the meantime."
  },
  {
   "t": "2026-07-10T16:12:11Z",
   "kind": "review_comment",
   "who": "furszy",
   "assoc": "MEMBER",
   "path": "src/flatfile.cpp",
   "commit": "fac9306686142f65cef2824088f81efc8884aacb",
   "in_reply_to": 3559484504,
   "text": "[quoted text omitted]\n\nCatching up can be painful too, especially if inconsistent state forces a full chain re-download for some reason, but that is not the main concern. An unclean shutdown could leave the wallet in an inconsistent state too, which seems far more serious to me. Even if the scenario is rare, I think it is worth avoiding an abrupt abort whenever possible. That is one of the reasons behind 35003 replacing the assertion for `FatalError` call.\n\n[quoted text omitted]\nDo you think that is the underlying reason we are not moving forward? Because that seems easy to address by opening an issue that lists all the remaining items and then crossing them off one by one.\n\nWe are not leaving the repository in a worse state with each change. In fact, the opposite is true. Each PR introduces strict improvements over the current state. The repository wouldn't be in a worse state after #35003, unless you see a regression introduced there? In such case, it would be good to know it to learn from it."
  },
  {
   "t": "2026-07-11T10:52:45Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "I think @furszy raises some good points here. It is one thing to posit that crashing should be fine, but another to actually being able to guarantee that. I think this is also close to impossible to guarantee.\n\n[quoted text omitted]\nI'm not too worried about this, at least when it comes to filesystem exceptions. This might not be true for others, like socket-level exceptions. I find the problem as sketched in #35003, i.e. entering ant mill-like doom loops, much more likely and bad. In my opinion this is most clearly solved by throwing exceptions and catching them as close to the module/thread boundaries as possible.\n\nArchitecturally, I don't think we are in a horrible situation either. We have a main thread that gracefully handles shutdown when notified. On an error, it gives us a second chance at cleanly flushing the state. We have shutdown and interrupt notification objects available pretty much for the entire runtime of the program. Naively, it doesn't seem overly complicated to catch exceptions at the top level of a thread and then trigger a shutdown notification.\n\nEDIT: Wanted to also add that with the guidance for using exceptions being cited here and in the other pull request, actual suggestions on where to handle exceptions is surprisingly slim."
  },
  {
   "t": "2026-07-14T14:08:47Z",
   "kind": "comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "text": "I have a weak inclination towards N.A.C.K-ing the approach, on the grounds that higher-level context-aware error handling is preferable against low-level context-free abort.\n\nPros:\n- A failure to query for disk space is likely a harsher error than low disk space condition\n- An abort on a fatal error in a low-level helper is easier to reason about, there is less cross-level dependencies\n- The extra logging of the error code and the new tests are good\n\nCons:\n- I find it inconsistent to handle low-disk-space condition in a context-aware manner, while handling cant-obtain-disk-space error case as an abort\n- Clean shutdown is preferable to abort even in \"will happen only rarely\" situations\n- I prefer returning errors from the low-level util -- `false` from `CheckDiskSpace`, `nullptr` from `Open`, which are handled by existing code in some way. With the extra error logs the root cause should be traceable.\n\nIf this PR would only add the error-logging of the OS error code, and maybe the new tests, without the aborts, I'd be happy to review it."
  },
  {
   "t": "2026-07-14T14:34:16Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nNot sure about this. How is this going to be reviewed/enforced in the future. Sure, it is trivial to add a try-catch in (let's say) the blockstorage module. However, that doesn't fix the issue in all other threads/locations: The index-init threads, the initload thread, the scheduler, .... So even if blockstorage is fixed, the same uncaught exception due to the same underlying reason will still uncleanly terminate the node. This seems fine, but also pointless to me, because there will be a bunch of code changes and there is a good chance the end user will not notice any difference. Also, even if all places were fixed, there is nothing preventing future pull requests from introducing an new call to `CheckDiskSpace` is a new thread in the future, silently re-introducing the problem that was attempted to be fixed. Sure, everyone in this thread is aware that `CheckDiskSpace` is throwing and that that needs to be considered. However, I am less sure about the reviewers in 2 years in a 250+ LOC pull request. It seems easy to miss, so I think either this problem is fully addressed and newly introducing it is rejected at compile time (or rejected with some tool in CI), or the problem is left as-is.\n\nIf there are 10 call sites of `CheckDiskSpace`, where 9 handle the failure and where 1 crashes, the  end-user will see that the node will crash in the same way as if all 10 sites were crashing.\n\n[quoted text omitted]\nSure, this was the initial pull request. Happy to change back to that.\n\nI think the problem here is that we need to decide whether it is fine for a rare IO failure to lead to a crash. If not, then there won't be an easy fix available, and likely many parts of the codebase need to be touched."
  },
  {
   "t": "2026-07-14T15:26:55Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nYes, I agree that would be bad and is not what I was suggesting, my suggestion was:\n\n[quoted text omitted]\nMost of our threads are spawned the same way through `TraceThread`. Maybe I'm being naive here, but passing in the process-wide interrupt to this function and then catching specific runtime exceptions and trigger the interrupt, seems like a fairly comprehensive way to handle this on the surface of it. But:\n\n[quoted text omitted]\nYes, still not sure."
  },
  {
   "t": "2026-07-14T15:58:24Z",
   "kind": "comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI don't think this works. If the scheduler thread dies and shortly before triggers a fatal shutdown, so that the wallet/etc is flushed, the shutdown will deadlock, because the scheduler is not available to flush?  Also, how can this be reviewed, when the index-ThreadSync thread or scheduler thread triggers an abort, drops state, and is expected to successfully flush stuff?\n\nI am sure it is possible to write an alternative fix here, but it seems tedious to write and review."
  },
  {
   "t": "2026-07-15T15:03:41Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/flatfile.cpp",
   "commit": "fac9306686142f65cef2824088f81efc8884aacb",
   "in_reply_to": 3559484504,
   "text": "[quoted text omitted]\n\nAs mentioned in my prior reply:\n\n[quoted text omitted]\nFixed in https://github.com/bitcoin/bitcoin/pull/35728\n\n[quoted text omitted]\nI'd say the stalled progress is because the goal of 35003 is unclear. Sure, it tries to not be off worse, but it leaves all the same errors originating from `CheckDiskSpace`, so instead of moving all error code paths from one behavior to another, 35003 is ending up with mixed handling. So all the issues that 35003 is trying to fix will still happen, just even more rarer. All of this seems like hand-waving, because the original issues are already extremely rare, but it is hard to draw a line what type of \"rare\" is acceptable. To me it seems that either all of this is rare enough to not think about it at all, or if it frequent enough, it should be fixed fully.\n\nEdit: Actually, the failure from `CheckDiskSpace` should be hit more frequently? So 35003 seems to be fixing the rare issues, and leaving the more frequent ones unfixed?"
  }
 ],
 "labels_log": [
  {
   "t": "2026-07-07T12:29:16Z",
   "action": "labeled",
   "label": "Utils/log/libs",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-07T12:47:34Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-07T13:19:05Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "maflcko"
  },
  {
   "t": "2026-07-07T13:51:38Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-07T15:37:29Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-09T13:54:04Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-09T15:00:36Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-07-09T13:29:35Z",
   "kind": "renamed",
   "who": "maflcko",
   "from": "util: Return false in CheckDiskSpace on exceptions",
   "to": "    util: Abort in CheckDiskSpace on rare exceptions"
  },
  {
   "t": "2026-07-09T13:30:42Z",
   "kind": "renamed",
   "who": "DrahtBot",
   "from": "    util: Abort in CheckDiskSpace on rare exceptions",
   "to": "util: Abort in CheckDiskSpace on rare exceptions"
  },
  {
   "t": "2026-07-10T15:29:43Z",
   "kind": "renamed",
   "who": "maflcko",
   "from": "util: Abort in CheckDiskSpace on rare exceptions",
   "to": "util: Abort in CheckDiskSpace/FlatFileSeq::Open on rare exceptions"
  }
 ],
 "text_chars": 16581,
 "text_tokens_estimate": 4145,
 "changed_paths": [
  "src/common/args.cpp",
  "src/flatfile.cpp",
  "src/index/blockfilterindex.cpp",
  "src/util/fs_helpers.cpp",
  "test/functional/feature_io_errors.py",
  "test/functional/test_runner.py"
 ],
 "files": [
  {
   "path": "src/common/args.cpp",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/flatfile.cpp",
   "add": 10,
   "del": 1
  },
  {
   "path": "src/index/blockfilterindex.cpp",
   "add": 2,
   "del": 1
  },
  {
   "path": "src/util/fs_helpers.cpp",
   "add": 11,
   "del": 1
  },
  {
   "path": "test/functional/feature_io_errors.py",
   "add": 130,
   "del": 0
  },
  {
   "path": "test/functional/test_runner.py",
   "add": 1,
   "del": 0
  }
 ],
 "test_lines": 131,
 "git": {
  "head": "fac9306686142f65cef2824088f81efc8884aacb",
  "head_matches_backup": true,
  "base": "81405fc7abbd1889f3978b8924e7acbe12b3403b",
  "commits": [
   {
    "sha": "faab1e4d3b",
    "subject": "test: Check handling of I/O erros from CheckDiskSpace (via Allocate)",
    "files": 4,
    "add": 136,
    "del": 1
   },
   {
    "sha": "fac9306686",
    "subject": "util: Abort in CheckDiskSpace on rare exceptions",
    "files": 3,
    "add": 28,
    "del": 11
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "ec3daaf177c43326",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}