Dfx .env incorrect canister ids generated?

I got following dfx config

  "canisters": {
    "internet_identity": {
      "type": "custom",
      "candid": "https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity.did",
      "wasm": "https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity_dev.wasm",
      "shrink": false,
      "remote": {
        "candid": "internet_identity.did",
        "id": {
          "ic": "rdmx6-jaaaa-aaaaa-aaadq-cai"
    "satellite": {
      "type": "custom",
      "candid": "https://raw.githubusercontent.com/buildwithjuno/juno/main/src/satellite/satellite.did",
      "wasm": "https://github.com/buildwithjuno/juno/releases/download/v0.0.8/satellite-v0.0.7.wasm.gz",
      "shrink": false
  "defaults": {
    "build": {
      "args": "",
      "packtool": ""
  "output_env_file": ".env",
  "version": 1

When I deploy the two canisters

dfx deploy internet_identity
dfx deploy satellite --argument ...

I get the following auto generated .env file:


Doesn’t look correct, I got twice the same canister id (the satellite) with two differents keys CANISTER_ID and CANISTER_ID_satellite. No mention of II nor its canister id.

Is there something wrong in my configuration or it’s a bug in the generation of the .env file?

Most likely a bug. I’ll flag it for the team

Note to self: Internal ticket

1 Like

Thanks Severin.

FYI I just redeployed and observered the .env file changing. I cleary saw first CANISTER_ID_internet_identity being written before being override by the next canister.

1 Like

This is expected behavior. Named canister ID environment variables are set for dependencies, so that they can be picked up by dependents, but not for the canister itself, and in some cases not when there is no dependency relationship. During a build, the .env file is accurate for the currently applied set of environment variables for the current build process; what it contains after the dust has settled, so to speak, doesn’t mean anything in particular. Its only real purpose is for communicating to build tools that have trouble with environment variables normally.

Is this documented somewhere because spontaneously, it feels like this approach gonna be super confusing for frontend developers. Why generating a .env if that files does not contains accurate environment variables?!?! If the canister ids are not accurate, then it would probably be worth having a post build hook that clean those from the .env file.

That said, I think the canister ids of dfx.json should be populated in the .env file accuratly. That way all frontend developers can get rid of the mumbo jumbo configuration required in webpack or vite.

Which variables are accurate depends on what’s supposed to be reading them. None of the variables are inaccurate. There can be no version of this feature that does not involve the variables changing from build to build, because canister IDs are different in local dev vs IC. What is reflected in the .env file is identical to what variables your build process receives the normal way, per build process. If you think this is unnecessary, or causes some kind of problem for you, you can delete the line from dfx.json; it is intentionally not default behavior but only part of the default template.

Thanks for the explanation.

To speak frankly, first of all, I think this is misleading. Frontend developers use .env file to handle the environment variables of their applications. Not per build process but all environment variables of their frontend apps. Packing envinronment variables that are per build process in it is therefore misleading.

e.g. when I opened this question I had a project with two canister but only the ID of the last one was populated in the .env file, does not make sense from a frontend developer perspective.

Secondly, from this point of view and if the strategy won’t gonna be corrected, opting out the behavior should in my opinion not be the default but the contrary. dfx should then not create .env file per default.

It’s there for maximum compatibility with tools, but it is opted into via the manifest, not out of. Again, if this is causing your tools to break in some way, I would love to hear about them or for an issue report on GitHub. As for not actually seeing II in your environment variables, if you add II to your dependencies field in dfx.json, you will.

1 Like

Does not break but, as I said, I think it leads to confusion for frontend devs but, my opinion so no need of opening an issue.

That was the original question in my above first post @AdamS.

Is there something wrong in my configuration …

Adding a dependencies does the trick.

Thanks for the feedback.

1 Like

We are going to continue discussing this, though. I don’t think your intuition that all canister ID’s that dfx is aware of is wrong. Dependencies are the intended config for how to tell dfx which canisters are related to each other, but that doesn’t mean the DX is ideal as it is currently

1 Like

This has been resolved in this PR. The .env file will now always include the canister IDs of the dependencies plus the IDs of canisters that have a know ID


Does this mean if using an internet_identity canister, it should now be included as a dependency in the frontend (along with “the” backend canister)?

Otherwise it indeed creates a very specific order in which canisters need to be initialized to have the benefits of an .env being created.

Maybe dfx.json’s .env entry could include an optional array entry, which verifies the included canister’s ids are in .env (or throw an error or automatically creates their id if it hasn’t been done yet).

Exactly. If you declare a canister as a dependency, then it is guaranteed to be available during the frontend build

That’s the point behind the dependencies you can declare :slightly_smiling_face:

Thanks! Would it be possible to also get the host and port included in .env (if development)?

Host and port are static - you can hard-code them just fine