You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Artifacts.cached never settles waiters when the effect fails, hanging plan #2981
Artifacts.cached(id) never settles its Deferred when the wrapped effect fails. The first caller gets the failure; every later caller with the same id awaits Deferred.await(deferred) forever.
// packages/alchemy/src/Artifacts.tsyield*artifacts.set(id,Deferred.await(deferred));constresult=yield*eff;// on failure, deferred is never completedyield*Deferred.succeed(deferred,result);
During plan, a resource with persisted state is diffed twice: once in resolveResource (stable attributes for downstream consumers) and once in diffResource. Drizzle.Schema caches detectDrift with Artifacts.cached, so when the first diff fails (for example #2980), the second waits forever, and so does every resource downstream of the schema. alchemy deploy sits at "Computing plan" until CI kills it, with no error. In --no-input mode nothing shows which resource is stuck, since failed diffs never emit plan.resource.completed.
Fix we are running
Settle waiters on any exit:
yield* artifacts.set(id, Deferred.await(deferred));
-const result = yield* eff;-yield* Deferred.succeed(deferred, result);+// Settle waiters on failure too, or every later caller hangs.+const result = yield* eff.pipe(Effect.onExit((exit) => Deferred.done(deferred, exit)));
yield* artifacts.set(id, result);
(In the TypeScript source the Deferred would need the error type, Deferred.make<A, Err>().) It may also be worth not caching failures at all, so a later caller retries instead of replaying the error.
Activity
sam-goodwin commentedon Nov 4, 2026
@BlankParticle you changed something here right?