overengineeringstudio / overengineeringstudio/effect-utils
Genie: GenieGenerationFailedError with ParseError masks real errors (missing module resolution via megarepo symlinks)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 82
- Forks
- 2
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 121
Description
Bug Summary
Running genie in a repo that imports genie runtime modules via megarepo symlinks fails on all files with two layered errors:
-
Root cause:
Cannot find module '@effect/platform'— Bun resolves transitive imports relative to the real path of the source file (inside the megarepo checkout), not the genie binary or the consumer repo. Since the megarepo checkout has nonode_modules/, all bare-specifier imports fail. -
Secondary bug: The Effect schema used to encode the generation result types the error channel as
never, so whenGenieGenerationFailedErrorpropagates, the schema encoding itself fails with aParseError, completely hiding the real per-file error messages.
Reproduction
Repro repo: https://github.com/schickling-repros/genie-generation-error
# In any repo using genie via megarepo symlinks (e.g. dotfiles):
MEGAREPO_ROOT_NEAREST=$PWD genie
Output (default)
The user only sees:
GenieGenerationFailedError: 9 file(s) failed to generate
ParseError: (parseJson <-> { readonly _tag: "Success"; ... } | { readonly _tag: "Failure"; ... })
└─ Type side transformation failure
└─ ...
└─ { readonly _tag: "Failure"; readonly cause: (CauseEncoded<never> <-> Cause<never>); ... }
└─ ["cause"]
└─ (CauseEncoded<never> <-> Cause<never>)
└─ Type side transformation failure
└─ Cause<never>
└─ CauseEncoded<never>
└─ { readonly _tag: "Fail"; readonly error: never }
└─ ["error"]
└─ Expected never, actual GenieGenerationFailedError: 9 file(s) failed to generate
Output (ndjson — reveals real errors)
MEGAREPO_ROOT_NEAREST=$PWD genie --output ndjson 2>&1
Per-file errors all look like:
GenieImportError: Failed to import .../ci.yml.genie.ts:
ResolveMessage: Cannot find module '@effect/platform' from
'/home/.../.megarepo/.../effect-utils/.../packages/@overeng/genie/src/runtime/package-json/context.ts'
The only file that succeeds is megarepo.json because megarepo-config/mod.ts has no transitive dependency on @effect/platform.
Root Cause Analysis
The genie binary spawns Bun to execute .genie.ts files. These files import from the genie runtime source via relative paths that resolve through megarepo symlinks:
// .oxlintrc.json.genie.ts
import { oxlintConfig } from './repos/effect-utils/packages/@overeng/genie/src/runtime/mod.ts'
The mod.ts barrel re-exports from package-json/mod.ts, which imports context.ts, which has:
import { FileSystem, Path } from '@effect/platform'
Bun resolves @effect/platform relative to the real path of context.ts inside the megarepo checkout (~/.megarepo/.../effect-utils/). That directory has no node_modules/ — dependencies are only installed inside the genie binary's embedded filesystem (/$bunfs/root/genie).
Two Distinct Issues
Issue A: Module resolution failure with symlinked sources
When genie runtime source files are consumed via symlinks (megarepo), Bun can't find the runtime's npm dependencies (@effect/platform, effect, etc.) because there's no node_modules at the symlink target.
Possible fixes:
- Bundle the genie runtime modules into the genie binary (they're currently loaded from source at runtime)
- Ship a pre-built runtime package that consumers can import (no transitive deps needed)
- Have genie inject Bun's module resolution paths to include the binary's embedded node_modules
Issue B: ParseError masks the real error
The schema used to encode the generation result (success/failure) types the error channel as Cause<never>. When a real error occurs (GenieGenerationFailedError), encoding fails because never doesn't accept it. This causes a ParseError that hides all per-file error details from the user.
Possible fix: Widen the error type in the result schema to accept GenieGenerationFailedError (or a broader error type).
Environment
- genie:
0.1.0+8f58904(committed 3 hours ago as of 2026-02-05) - bun:
1.3.8 - OS: Linux x86_64 (NixOS)
- megarepo checkout:
~/.megarepo/github.com/overengineeringstudio/effect-utils/refs/heads/main/(nonode_modules/)
Workaround
None found. Running pnpm install in the megarepo checkout might work but defeats the purpose of the hermetic genie binary.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the symlinked runtime path through mod.ts, package-json/mod.ts, and context.ts, then inspect the generation result schema involved in encoding GenieGenerationFailedError. Reproduce with MEGAREPO_ROOT_NEAREST=$PWD genie and compare default output with --output ndjson. Done means runtime imports resolve through the hermetic binary and generation failures retain their per-file error details instead of becoming ParseError.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bun, typescript
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100