Extension spawn: put Kaimon's active environment on JULIA_LOAD_PATH, not pkgdir #61

Merged
mthelm85 merged 1 commit from fix-extension-load-path into main 2026-07-17 17:18:18 -07:00
mthelm85 commented 2026-07-15 09:37:56 -07:00 (Migrated from github.com)

Extension spawn: put Kaimon's active environment on JULIA_LOAD_PATH, not pkgdir

Problem

Every extension crashes on boot when Kaimon is installed from the registry (pkg> app add Kaimon). From the extension log (slate extension, Windows, Julia 1.12.6, but the failure is platform-independent):

ERROR: LoadError: ArgumentError: Package JSON [682c06a0-de6a-54ab-a142-c8b1cf79cde6] is required but does not seem to be installed:
 - Run `Pkg.instantiate()` to install all recorded dependencies.
...
in expression starting at C:\Users\mthel\.julia\packages\Kaimon\35M1a\src\Kaimon.jl:2

Kaimon's dashboard shows the extension crash-looping: Extension 'slate' crashed (was starting, exit=1, after ~7s) × 3 attempts.

spawn_extension! builds the subprocess load path as:

kaimon_project = pkgdir(@__MODULE__)
env["JULIA_LOAD_PATH"] = _join_load_path("@", kaimon_project, "@v#.#", "@stdlib")

For a registry/app install, pkgdir(Kaimon) is the depot package dir (~/.julia/packages/Kaimon/<slug>), which ships a Project.toml but no Manifest.toml. That environment claims the name Kaimon during load-path resolution (it is the project package), but without a manifest none of Kaimon's deps can be resolved — so the boot script's using Kaimon fails and the extension exits. Users can't repair it in place either: depot package dirs are write-protected, so Pkg.instantiate() against them dies with Permission denied (and the boot script's own Pkg.resolve() fails the same way).

This only works today when Kaimon runs from a dev checkout, whose project directory carries an instantiated manifest.

Fix

Use the running instance's active environment for the load-path entry instead of pkgdir. For an app install that's ~/.julia/environments/apps/Kaimon and for a dev checkout it's the checkout project — both have instantiated manifests that resolve Kaimon and its deps. Fall back to pkgdir(Kaimon) when the active project has no manifest:

kaimon_project = let active = Base.active_project(), pd = pkgdir(@__MODULE__)
    mf = active === nothing ? nothing : Base.project_file_manifest_path(active)
    (mf !== nothing && isfile(mf)) ? dirname(active) : pd
end

Base.project_file_manifest_path also honors versioned manifests (Manifest-v1.x.toml).

Testing

Reproduced with app add Kaimon + a registered extension: before the change the extension crash-loops with the JSON resolution error above; with Kaimon's deps reachable through an instantiated environment on the load path, the extension boots and serves its tools.

The registered extension's own --project has the same exposure: KaimonSlate.register_extension() defaults project_path to pkgdir(KaimonSlate), which is likewise manifest-less for registry installs, and the boot script's Pkg.resolve() cannot write there. Filing separately since the right fix (Kaimon managing instantiated environments for extensions?) is a design call.

# Extension spawn: put Kaimon's active environment on `JULIA_LOAD_PATH`, not `pkgdir` ## Problem Every extension crashes on boot when Kaimon is installed from the registry (`pkg> app add Kaimon`). From the extension log (`slate` extension, Windows, Julia 1.12.6, but the failure is platform-independent): ``` ERROR: LoadError: ArgumentError: Package JSON [682c06a0-de6a-54ab-a142-c8b1cf79cde6] is required but does not seem to be installed: - Run `Pkg.instantiate()` to install all recorded dependencies. ... in expression starting at C:\Users\mthel\.julia\packages\Kaimon\35M1a\src\Kaimon.jl:2 ``` Kaimon's dashboard shows the extension crash-looping: `Extension 'slate' crashed (was starting, exit=1, after ~7s)` × 3 attempts. `spawn_extension!` builds the subprocess load path as: ```julia kaimon_project = pkgdir(@__MODULE__) env["JULIA_LOAD_PATH"] = _join_load_path("@", kaimon_project, "@v#.#", "@stdlib") ``` For a registry/app install, `pkgdir(Kaimon)` is the depot package dir (`~/.julia/packages/Kaimon/<slug>`), which ships a `Project.toml` but **no `Manifest.toml`**. That environment claims the name `Kaimon` during load-path resolution (it is the project package), but without a manifest none of Kaimon's deps can be resolved — so the boot script's `using Kaimon` fails and the extension exits. Users can't repair it in place either: depot package dirs are write-protected, so `Pkg.instantiate()` against them dies with `Permission denied` (and the boot script's own `Pkg.resolve()` fails the same way). This only works today when Kaimon runs from a dev checkout, whose project directory carries an instantiated manifest. ## Fix Use the **running instance's active environment** for the load-path entry instead of `pkgdir`. For an app install that's `~/.julia/environments/apps/Kaimon` and for a dev checkout it's the checkout project — both have instantiated manifests that resolve Kaimon and its deps. Fall back to `pkgdir(Kaimon)` when the active project has no manifest: ```julia kaimon_project = let active = Base.active_project(), pd = pkgdir(@__MODULE__) mf = active === nothing ? nothing : Base.project_file_manifest_path(active) (mf !== nothing && isfile(mf)) ? dirname(active) : pd end ``` `Base.project_file_manifest_path` also honors versioned manifests (`Manifest-v1.x.toml`). ## Testing Reproduced with `app add Kaimon` + a registered extension: before the change the extension crash-loops with the JSON resolution error above; with Kaimon's deps reachable through an instantiated environment on the load path, the extension boots and serves its tools. ## Related The registered extension's own `--project` has the same exposure: `KaimonSlate.register_extension()` defaults `project_path` to `pkgdir(KaimonSlate)`, which is likewise manifest-less for registry installs, and the boot script's `Pkg.resolve()` cannot write there. Filing separately since the right fix (Kaimon managing instantiated environments for extensions?) is a design call.
kahliburke commented 2026-07-17 00:09:48 -07:00 (Migrated from github.com)

Ah, isn't Julia package management fun? I'll take a look, thanks for the effort on this.

Ah, isn't Julia package management fun? I'll take a look, thanks for the effort on this.
Sign in to join this conversation.
No description provided.