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
methods inherited via Object.setPrototypeOf(obj, proto) run with this=undefined — effect Pipeable/Tag statics return the wrong pipe stage (blocks web.ts, 'Not a valid effect: undefined') #6475
HealthLive = HttpApiBuilder.group(Api, "health", ...) — and group returns Router.use((router) => ...) where Router is class Router extends HttpRouter.Tag("@effect/platform/HttpApiBuilder/Router")<Router>() {}.
probe44 — Tag statics misbehave
Recreating the Tag shape directly (class R2 extends HttpRouter.Tag("probe44/R2")<R2>() {}):
check
node
perry
pipe(1, f, g) / 4 fns / method-style .pipe
✓
✓ (all fine)
R2.key
✓
✓
R2.Live
Layer
Layer ✓
R2.use(f)
Layer
function (isLayer false)
R2.unwrap(f)
Layer object
function
use is an own-prop ARROW on the factory's TagClass (TagClass_.use = (f) => TagClass_.pipe(Effect.flatMap(f), Layer.scopedDiscard, Layer.provide(TagClass_.Live))), inherited by R2 through the parent function object. The returned function is consistent with the pipe chain's LAST stage (Layer.provide(live), a data-last curried fn) never being applied — i.e. TagClass_.pipe(...) misfired on the receiver/arguments. TagClass's prototype is Object.getPrototypeOf(Context.GenericTag(id)) (a two-hop chain to Pipeable's pipe() { return pipeArguments(this, arguments) }).
probe45 — a minimal this-drop divergence in the same family
constProto: any={collect(this: any, ...args: any[]){return[this?.tag,args.length, ...args]}}functionF(){};Object.setPrototypeOf(F,Proto);(Fasany).tag="fn-recv"constO: any={tag: "obj-recv"};Object.setPrototypeOf(O,Proto)(Fasany).collect(10,20,30)// node ["fn-recv",3,10,20,30] | perry ["fn-recv",3,10,20,30] ✓O.collect(10,20,30)// node ["obj-recv",3,10,20,30] | perry ["null",3,10,20,30] ✗O.fixed(1,2)// same: this dropped (null) for the OBJECT receiver
A method inherited through Object.setPrototypeOf(plainObject, proto) runs with this = undefined under perry (function-object receivers, own-prop closures, and arguments-based variadics all work). This is the same resolution family pipeArguments(this, arguments) sits in — with this undefined mid-chain, effect's Pipeable composition returns the wrong stage.
Impact
HttpApiBuilder.group(...) returns a function instead of a Layer, and the poison propagates lazily until the fiber run loop rejects an undefined — blocking the web.ts app (the 4th of the effect repro; the other three are byte-identical to node).
Repro files: probes 43/44/45 as above (no server needed for 44/45).
The Object.setPrototypeOf(obj, proto)this=undefined / Tag-static wrong-pipe-stage bug → fix: static/namespace resolution for effect Tag & Schema — web.ts server starts (#6475) #6496 (fix: static/namespace resolution for effect Tag & Schema): bind this to the receiver on both proto-method call paths, substitute a function-object call-site this for canonical bound class methods, invalidate the cached dispatch strategy on closure registration, walk the parent-closure chain for static-member CALLs (class X extends Tag(id)() inherits static use/serve), and resolve namespace-member spread calls to the function rather than a same-named class.
The residual Not a valid effect: undefined → fix(hir): abstract class fields are type-only, emit no runtime slot #6499 (fix(hir): abstract class fields are type-only, emit no runtime slot): @effect/platform's HttpBody declares abstract readonly _tag on the base with concrete _tag on Uint8ArrayImpl/EmptyImpl/RawImpl. Perry lowered the abstract field into a duplicate runtime slot, so the response writer's switch (body._tag) read undefined, fell through, and returned undefined.
effect-compiled-experiment web.ts now serves byte-identical to Node (homepage + JSON API). Closing as resolved.
Activity
fix(runtime): substitute a function-object call-site this for canonic…
fix(runtime): invalidate cached dispatch strategy on closure registra…
fix(runtime): static-member CALL walks the parent-closure chain (#6475)
fix(codegen): namespace-member spread call resolves the function, not…
fix: static/namespace resolution for effect Tag & Schema — web.ts ser…
chore(release): v0.5.1260 — effect web-server fixes (#6496, #6499)
proggeramlug commentedon Jul 17, 2026
Fixed — both root causes landed on main:
Object.setPrototypeOf(obj, proto)this=undefined/ Tag-static wrong-pipe-stage bug → fix: static/namespace resolution for effect Tag & Schema — web.ts server starts (#6475) #6496 (fix: static/namespace resolution for effect Tag & Schema): bindthisto the receiver on both proto-method call paths, substitute a function-object call-sitethisfor canonical bound class methods, invalidate the cached dispatch strategy on closure registration, walk the parent-closure chain for static-member CALLs (class X extends Tag(id)()inherits staticuse/serve), and resolve namespace-member spread calls to the function rather than a same-named class.Not a valid effect: undefined→ fix(hir): abstract class fields are type-only, emit no runtime slot #6499 (fix(hir): abstract class fields are type-only, emit no runtime slot):@effect/platform'sHttpBodydeclaresabstract readonly _tagon the base with concrete_tagonUint8ArrayImpl/EmptyImpl/RawImpl. Perry lowered the abstract field into a duplicate runtime slot, so the response writer'sswitch (body._tag)readundefined, fell through, and returnedundefined.effect-compiled-experiment
web.tsnow serves byte-identical to Node (homepage + JSON API). Closing as resolved.fix: proxy-forwarded class-method `this` binding — TUI-init undefined…
fix(codegen): route const rest exports through the closure spread call (