Keep the class and cause of cached key fetch failures in KvKeyCache #1168
Copy link
Copy link
Closed
Copy link
Labels
component/signaturesOIP or HTTP/LD Signatures relatedOIP or HTTP/LD Signatures relateddifficulty/intermediateIntermediate levelIntermediate level
Milestone
Description
Activity
- addedcomponent/signaturesOIP or HTTP/LD Signatures relatedOIP or HTTP/LD Signatures relateddifficulty/intermediateIntermediate levelIntermediate level
on Sep 30, 2026 @dahlia Hi! I'd like to work on this issue. Would it be okay for me to take it on?
I've looked through
KvKeyCacheand the existing timeout tests. My plan is to preserve the known error types, their relevant fields, and cause information while keeping the cache format compatible with older versions. I'll also extend the regression coverage for cached timeout and DNS failures, and old-format entries.@junghoon-vans Sure, thanks!
- added a commit that references this issue
on Oct 5, 2026 - linked a pull request that will close this issuePreserve cached key fetch failure details #1237
on Oct 5, 2026
Metadata
Metadata
Assignees
Labels
component/signaturesOIP or HTTP/LD Signatures relatedOIP or HTTP/LD Signatures relateddifficulty/intermediateIntermediate levelIntermediate level
Type
Fields
Priority
None yet
Effort
None yet
Background
fetchKeyDetailed()stores why fetching a key failed in the key cache, so thatverifyRequestDetailed()can report the samekeyFetchErrorfor later requests without fetching the key again. When the failure has no HTTP response,KvKeyCache.setFetchError()stores only the error'snameandmessage(packages/fedify/src/federation/keycache.ts), andKvKeyCache.getFetchError()rebuilds it as a plainErrorwith that name.So a cached failure is not the same as the one it was made from:
FetchError(or of any other class), soerror instanceof FetchErrorfails;causeis gone;FetchError.urlis gone.This matters more since #1131, which makes the built-in document loaders throw a
FetchErrorwithout a response on a timeout, and documentserror.causebeing aDOMExceptionnamed"TimeoutError"as the way to tell a timeout apart. The first request whose key fetch times out gets that error, but every request within the unavailable key TTL (10 minutes by default) gets a plainErrorwhose only trace of the timeout is its message,…: Timed out after 10000 ms. The Timeouts section of docs/manual/context.md notes this as a limitation. The same applies to other failures without a response, such as DNS failures (UrlErrorwith itsreason) and disallowed private addresses.Proposed work
Keep enough of a failure without a response in
KvKeyCacheto rebuild what applications check, e.g.:FetchError,UrlError), withFetchError.urlandUrlError.reason;nameandmessageof thecause, rebuilt as aDOMExceptionwhen it was one.Entries stored by earlier versions have only
errorNameanderrorMessage, so reading them must keep working, and a new entry should still be readable by an older version during a rolling upgrade (e.g., by adding fields rather than changing the existing ones). Unknown error classes can fall back to the current behavior.Tests
verifyRequestDetailed()with aFetchErrorwhosecauseis named"TimeoutError", both the first time and when read back from a newKvKeyCacheover the sameKvStore.UrlErrorclass andreasonwhen cached.