# Why dependencies of a dependency are not available in the environment?

**URL:** <https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [May 7, 2025, 4:22pm UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810 "2025-05-07T16:22:57Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [May 7, 2025, 4:22pm UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810/1 "2025-05-07T16:22:57Z")

</div>

Hi, I have defined an environment (`Project.toml`) that depends on two (local) packages: package A and B. Package B depends on `OrdinaryDiffEq`.

Question: Why, when I activate an environment in which I have added (via `develop`) these two packages, I cannot do `using OrdinaryDiffEq`?

---

<div class="post-metadata">

**Author:** ![hexaeder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hexaeder/32/24403_2.png) [@hexaeder](https://discourse.julialang.org/u/hexaeder)\
**Post date:** [May 7, 2025, 4:29pm UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810/2 "2025-05-07T16:29:11Z")

</div>

The fact that B depends on OrdinaryDiffEq is an internal detail and might possibly change in the future. You can use `using B.OrdinaryDiffEq` to still access or use Reexport.jl in `B` to expose it. Maybe even plain `export OrdinaryDiffEq`.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [May 7, 2025, 4:46pm UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810/3 "2025-05-07T16:46:40Z")

</div>

The best answer here is to just add `OrdinaryDiffEq` yourself. Doing so has no cost, and will make your code clearer.

---

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [May 7, 2025, 4:49pm UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810/4 "2025-05-07T16:49:25Z")

</div>

Yes, but then it looks like duplication: now not only the environment but also the package itself declare the same dependencies (there are three of them right now).

---

<div class="post-metadata">

**Author:** ![hexaeder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hexaeder/32/24403_2.png) [@hexaeder](https://discourse.julialang.org/u/hexaeder)\
**Post date:** [May 7, 2025, 4:58pm UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810/5 "2025-05-07T16:58:05Z")

</div>

I totally agree, generally it’s best to add. But I do think there are a few valid usecases for sub-import. For example, A depends on B, but in the documentation of A you want to use B in an example. Now you have 3 options:

- Add B and with a separate compat entry to your doc env, but this can mess with CompatHelper as it has to bump the version if B in two places simultaneously.
- Add B with uncapped compat like \>0.0.1, because you know it will be constrained by A, feels a bit hacky.
- Use `A.B`, which also feels hacky.

Personally, I tend to use 2) but I think this is a valid usecase for 3).

---

<div class="post-metadata">

**Author:** ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)\
**Post date:** [May 8, 2025, 12:13am UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810/6 "2025-05-08T00:13:11Z")

</div>

> [@dmitry-kabanov](#):
>
> Yes, but then it looks like duplication

It’s not though. Direct and indirect dependencies mean different things. As @hexaeder said:

> [@hexaeder](#):
>
> The fact that B depends on OrdinaryDiffEq is an internal detail and might possibly change in the future

Just to give a concrete example, let’s say I have the following modules in package form:

```julia
# Package Foo.jl
module Foo

using Bar

export hello_world 

"""
Returns the `String` "Hello, World!"
"""
function hello_world()
    h = Bar.hello()
    w = Bar.world()
    return string(h, ", ", w, "!")
end

end

# Package Bar.jl
module Bar 

hello() = "Hello"
world() = "World"

end

```

Now you in your project add `Foo`, and also really want to use `Bar.world()` on its own. You can avoid making Bar a direct dependency, and do `import Foo.Bar`, but if `Foo` decides to drop the dependency on `Bar` and simply define `hello_world() = "Hello, World!"`, this would not be a breaking change from the perspective of the `Foo`, but it **would** break your package code, and Pkg would not be able to help you prevent that.

Of course, if you’re just developing something for your own use and don’t want to bother with adding the other package to your environment, you don’t **have** to. It’s your code, you do what you like. But it’s not duplication. It’s free from the perspective of the package manager (the Manifest.toml will be identical), but it has a different meaning and there are different guarantees from the perspective of the broader ecosystem

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 8, 2025, 12:28am UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810/7 "2025-05-08T00:28:53Z")

</div>

> [@dmitry-kabanov](#):
>
> it looks like duplication: now not only the environment but also the package itself declare the same dependencies

How does it look like duplication exactly? The project or manifest file shouldn’t list any package twice, the minimum statement `using A, B, OrdinaryDiffEq` doesn’t have redundancies, and it’s routine to repeat module or package names in different import statements.

---

<div class="post-metadata">

**Author:** ![dmitry-kabanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmitry-kabanov/32/52639_2.png) [@dmitry-kabanov](https://discourse.julialang.org/u/dmitry-kabanov)\
**Post date:** [May 8, 2025, 3:34pm UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810/8 "2025-05-08T15:34:57Z")

</div>

Thank you all for the answers, but I really struggle to understand them 🙂

So, I have a code which has two local Julia packages (in `lang_julia` folder in the project root), and I want to abstract out the user from this detail, so I want to provide a `Project.toml` at the project root that declares two local packages as dependencies:

```julia
[deps]
PackageA = "07cfd324-e924-40a7-85fa-5e46307e7ad7"
PackageB = "daff4927-7858-4806-96da-915047fb441c"

```

Now, PackageB depends on `OrdinaryDiffEq`, so inside the folder `lang_julia/PackageB` I have another `Project.toml`:

```julia
name = "PackageB"
uuid = "daff4927-7858-4806-96da-915047fb441c"
version = "0.1.0"

[deps]
MsgPack = "99f44e22-a591-53d1-9472-aa23ef4bd671"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"

```

However, I need to `include` some Julia modules inside the environment, because it is an embedded Julia interpreter, and I need it to load these modules dynamically (it is not known in advance, what module will be requested).

If such a module wants to do `OrdinaryDiffEq`, then it does not work, as the root-level `Project.toml` does not include this package as a dependency.

The only working solution that I have so far is to include it in the root-level `Project.toml`, and then I have duplication, as the same dependency is written in two different `Project.toml`s.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 8, 2025, 4:37pm UTC](https://discourse.julialang.org/t/why-dependencies-of-a-dependency-are-not-available-in-the-environment/128810/9 "2025-05-08T16:37:12Z")

</div>

> [@dmitry-kabanov](#):
>
> include it in the root-level `Project.toml`, and then I have duplication, as the same dependency is written in two different `Project.toml`s.

Thanks for clarifying, that makes perfect sense. A package being recorded as a dependency across several project files is actually routine. Package managers will attempt to resolve dependencies for a particular environment, in other words it will try to find one version of each package that is compatible with all project files and just load that one for the environment. If it’s impossible or brittle, it’s called dependency hell, and it takes effort across the ecosystem to keep packages compatible with each other across time with some leeway.

As for your case, you should know the versions of `OrdinaryDiffEq` with which package `B` is compatible (`[compat]` section of project file), so you could just use that for your environment. It only appears redundant because you intend to keep the environment and `B` equally updated for now. But say you’re done with your environment in the next year (locking down its `[compat]` with upper version bounds) but continue to develop `B` for the next 10 years; if you have to dust off your environment to reproduce results from a decade ago, you _want_ the environment’s project file to refuse to use the newer incompatible versions of `OrdinaryDiffEq` and `B` (which people have pointed out may not even depend on `OrdinaryDiffEq` anymore). A very common way for old notebooks failing within a few years is a poorly restricted project file (or whatever the language uses for compatibility declarations) or failing to save one at all.
