firebase-tools: firebase emulators:start always ignores `.env` file and throws “Attempted to write param-defined key” error

[REQUIRED] Environment info

firebase-tools: 11.16.0

Platform: macOS Ventura 13.0

[REQUIRED] Test case

https://github.com/pan93412/firebase-question-221105/tree/373cce9e7093f707198cfa0ff2fbba561c6b167c

[REQUIRED] Steps to reproduce

  1. Create a project that reads environment variables with firebase-functions/params, see “Test case.”
  2. Remove all the .env* files – ensure the following .env file is generated by firebase-tools.
  3. Run pnpm serve to build from TypeScript src and run firebase emulators:start
  4. firebase-tools prompts to type my DISCORD_TOKEN and GUILD – it is expected.
  5. Then, it generates a .env-[project name] file, and the function starts correctly.
  6. <kbd>⌘C</kbd>, and re-run pnpm serve.
  7. It requires me to type the variables that has inputted in 4. and saved in 5. – it is unexpected.
  8. After typing the same value typed in 4. and press <kbd>Enter</kbd>, it throws the following message:
    Failed to load function definition from source: FirebaseError: Attempted to write param-defined key DISCORD_TOKEN to .env files, but it was already defined.
    
  9. After throwing, I can not see any functions starts, resulting me to remove the generated .env to let it work again.

The screencast:

https://user-images.githubusercontent.com/28441561/200131049-e1ad4974-3dc2-46d5-8ac8-24603da4964a.mp4

[REQUIRED] Expected behavior

  • It should read our .env file, and not prompt for typing again.
  • “.env write exception” should not block the whole start process.

[REQUIRED] Actual behavior

> functions@ serve /Volumes/Dev/Projects/ciscc-v3-backend/functions
> npm run build && firebase emulators:start --only functions "--debug"


> build
> tsc

[2022-11-05T16:28:45.339Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
[2022-11-05T16:28:45.339Z] > authorizing via signed-in user (pan93412@gmail.com)
i  emulators: Starting emulators: functions {"metadata":{"emulator":{"name":"hub"},"message":"Starting emulators: functions"}}
[2022-11-05T16:28:45.584Z] [logging] Logging Emulator only supports listening on one address (127.0.0.1). Not listening on ::1
[2022-11-05T16:28:45.584Z] assigned listening specs for emulators {"user":{"hub":[{"address":"127.0.0.1","family":"IPv4","port":4400},{"address":"::1","family":"IPv6","port":4400}],"ui":[{"address":"127.0.0.1","family":"IPv4","port":4000},{"address":"::1","family":"IPv6","port":4000}],"logging":[{"address":"127.0.0.1","family":"IPv4","port":4500}]},"metadata":{"message":"assigned listening specs for emulators"}}
[2022-11-05T16:28:45.591Z] [hub] writing locator at /var/folders/cn/c_n1ss3x7rx78k6mpw9t6bsm0000gn/T/hub-ciscc-18220.json
[2022-11-05T16:28:45.768Z] [functions] Functions Emulator only supports listening on one address (127.0.0.1). Not listening on ::1
[2022-11-05T16:28:45.768Z] [eventarc] Eventarc Emulator only supports listening on one address (127.0.0.1). Not listening on ::1
[2022-11-05T16:28:45.768Z] late-assigned ports for functions and eventarc emulators {"user":{"hub":[{"address":"127.0.0.1","family":"IPv4","port":4400},{"address":"::1","family":"IPv6","port":4400}],"ui":[{"address":"127.0.0.1","family":"IPv4","port":4000},{"address":"::1","family":"IPv6","port":4000}],"logging":[{"address":"127.0.0.1","family":"IPv4","port":4500}],"functions":[{"address":"127.0.0.1","family":"IPv4","port":5001}],"eventarc":[{"address":"127.0.0.1","family":"IPv4","port":9299}]},"metadata":{"message":"late-assigned ports for functions and eventarc emulators"}}
⚠  functions: The following emulators are not running, calls to these services from the Functions emulator will affect production: auth, firestore, database, hosting, pubsub, storage {"metadata":{"emulator":{"name":"functions"},"message":"The following emulators are not running, calls to these services from the Functions emulator will affect production: \u001b[1mauth, firestore, database, hosting, pubsub, storage\u001b[22m"}}
✔  functions: Using node@16 from host. {"metadata":{"emulator":{"name":"functions"},"message":"Using node@16 from host."}}
[2022-11-05T16:28:45.775Z] defaultcredentials: writing to file /Users/pan93412/.config/firebase/pan93412_gmail_com_application_default_credentials.json
[2022-11-05T16:28:45.779Z] Setting GAC to /Users/pan93412/.config/firebase/pan93412_gmail_com_application_default_credentials.json {"metadata":{"emulator":{"name":"functions"},"message":"Setting GAC to /Users/pan93412/.config/firebase/pan93412_gmail_com_application_default_credentials.json"}}
[2022-11-05T16:28:45.780Z] >>> [apiv2][query] GET https://firebase.googleapis.com/v1beta1/projects/ciscc-18220/adminSdkConfig [none]
[2022-11-05T16:28:46.214Z] <<< [apiv2][status] GET https://firebase.googleapis.com/v1beta1/projects/ciscc-18220/adminSdkConfig 200
[2022-11-05T16:28:46.214Z] <<< [apiv2][body] GET https://firebase.googleapis.com/v1beta1/projects/ciscc-18220/adminSdkConfig {"projectId":"ciscc-18220","storageBucket":"ciscc-18220.appspot.com"}
[2022-11-05T16:28:46.235Z] Ignoring unsupported arg: auto_download {"metadata":{"emulator":{"name":"ui"},"message":"Ignoring unsupported arg: auto_download"}}
[2022-11-05T16:28:46.235Z] Ignoring unsupported arg: port {"metadata":{"emulator":{"name":"ui"},"message":"Ignoring unsupported arg: port"}}
[2022-11-05T16:28:46.235Z] Starting Emulator UI with command {"binary":"node","args":["/Users/pan93412/.cache/firebase/emulators/ui-v1.11.1/server/server.js"],"optionalArgs":[],"joinArgs":false} {"metadata":{"emulator":{"name":"ui"},"message":"Starting Emulator UI with command {\"binary\":\"node\",\"args\":[\"/Users/pan93412/.cache/firebase/emulators/ui-v1.11.1/server/server.js\"],\"optionalArgs\":[],\"joinArgs\":false}"}}
i  ui: Emulator UI logging to ui-debug.log {"metadata":{"emulator":{"name":"ui"},"message":"Emulator UI logging to \u001b[1mui-debug.log\u001b[22m"}}
[2022-11-05T16:28:46.339Z] Web / API server started at 127.0.0.1:4000
 {"metadata":{"emulator":{"name":"ui"},"message":"Web / API server started at 127.0.0.1:4000\n"}}
[2022-11-05T16:28:46.340Z] Web / API server started at ::1:4000
 {"metadata":{"emulator":{"name":"ui"},"message":"Web / API server started at ::1:4000\n"}}
i  functions: Watching "/Volumes/Dev/Projects/ciscc-v3-backend/functions" for Cloud Functions... {"metadata":{"emulator":{"name":"functions"},"message":"Watching \"/Volumes/Dev/Projects/ciscc-v3-backend/functions\" for Cloud Functions..."}}
[2022-11-05T16:28:46.502Z] Validating nodejs source
[2022-11-05T16:28:50.025Z] > [functions] package.json contents: {
  "name": "functions",
  "scripts": {
    "lint": "eslint --ext .js,.ts .",
    "build": "tsc",
    "build:watch": "tsc --watch",
    "serve": "npm run build && firebase emulators:start --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "type": "module",
  "engines": {
    "node": "16"
  },
  "main": "lib/index.js",
  "dependencies": {
    "@firebase/app-types": "^0.8.1",
    "discord-api-types": "^0.37.16",
    "discord.js": "^14.6.0",
    "firebase-admin": "^11.2.0",
    "firebase-functions": "^4.0.2",
    "nominal-types": "^0.1.2"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^5.12.0",
    "@typescript-eslint/parser": "^5.12.0",
    "eslint": "^8.9.0",
    "eslint-config-google": "^0.14.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-import": "^2.25.4",
    "firebase-functions-test": "^3.0.0",
    "firebase-tools": "^11.16.0",
    "jest": "^29.2.2",
    "typescript": "5.0.0-dev.20221103"
  },
  "private": true
}
[2022-11-05T16:28:50.026Z] Building nodejs source
[2022-11-05T16:28:50.026Z] Analyzing nodejs backend spec
[2022-11-05T16:28:50.028Z] Could not find functions.yaml. Must use http discovery
[2022-11-05T16:28:50.194Z] Serving at port 9005

[2022-11-05T16:28:50.517Z] Got response from /__/functions.yaml {"endpoints":{"addnumbers":{"availableMemoryMb":null,"timeoutSeconds":null,"minInstances":null,"maxInstances":null,"ingressSettings":null,"concurrency":null,"serviceAccountEmail":null,"vpc":null,"platform":"gcfv2","labels":{},"callableTrigger":{},"entryPoint":"addnumbers"},"getstickers":{"availableMemoryMb":null,"timeoutSeconds":null,"minInstances":null,"maxInstances":null,"ingressSettings":null,"concurrency":null,"serviceAccountEmail":null,"vpc":null,"platform":"gcfv2","labels":{},"httpsTrigger":{},"entryPoint":"getstickers"}},"specVersion":"v1alpha1","requiredAPIs":[],"params":[{"name":"DISCORD_TOKEN","type":"string"},{"name":"GUILD","type":"string"}]}
[2022-11-05T16:28:50.524Z] shutdown requested via /__/quitquitquit

? Enter a string value for DISCORD_TOKEN: 
? Enter a string value for GUILD: 
i  functions: Loaded environment variables from .env.ciscc-18220. 
i  functions: Loaded environment variables from .env.ciscc-18220. 
⬢  functions: Failed to load function definition from source: FirebaseError: Attempted to write param-defined key DISCORD_TOKEN to .env files, but it was already defined. {"metadata":{"emulator":{"name":"functions"},"message":"Failed to load function definition from source: FirebaseError: Attempted to write param-defined key DISCORD_TOKEN to .env files, but it was already defined."}}

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://127.0.0.1:4000/               │
└─────────────────────────────────────────────────────────────┘

┌───────────┬────────────────┬─────────────────────────────────┐
│ Emulator  │ Host:Port      │ View in Emulator UI             │
├───────────┼────────────────┼─────────────────────────────────┤
│ Functions │ 127.0.0.1:5001 │ http://127.0.0.1:4000/functions │
└───────────┴────────────────┴─────────────────────────────────┘
  Emulator Hub running at 127.0.0.1:4400
  Other reserved ports: 4500

Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.
 
^C[2022-11-05T16:28:59.201Z] Received signal SIGINT (Ctrl-C) 1
 
i  emulators: Received SIGINT (Ctrl-C) for the first time. Starting a clean shutdown. 
i  emulators: Please wait for a clean shutdown or send the SIGINT (Ctrl-C) signal again to stop right now. 
i  emulators: Shutting down emulators. {"metadata":{"emulator":{"name":"hub"},"message":"Shutting down emulators."}}
i  ui: Stopping Emulator UI {"metadata":{"emulator":{"name":"ui"},"message":"Stopping Emulator UI"}}
⚠  Emulator UI has exited upon receiving signal: SIGINT 
i  functions: Stopping Functions Emulator {"metadata":{"emulator":{"name":"functions"},"message":"Stopping Functions Emulator"}}
i  eventarc: Stopping Eventarc Emulator {"metadata":{"emulator":{"name":"eventarc"},"message":"Stopping Eventarc Emulator"}}
i  hub: Stopping emulator hub {"metadata":{"emulator":{"name":"hub"},"message":"Stopping emulator hub"}}
i  logging: Stopping Logging Emulator {"metadata":{"emulator":{"name":"logging"},"message":"Stopping Logging Emulator"}}
keywords: Attempted to write param-defined key, Failed to load function definition from source, environment variable, .env, params

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 9
  • Comments: 24 (10 by maintainers)

Commits related to this issue

Most upvoted comments

I spent a couple of hours on this. In my case, I had env variables starting with FIREBASE_. Renaming these variables fixed it for me. Found the tip here: https://medium.com/rockedscience/fixing-the-firebase-functions-configuration-loading-issues-7c483b47e5f3

Give this author a clap if it helps you!

What to do if the settings are not loaded Check the following:

  • The firebase-functions package MUST be version 3.18.0 or newer
  • The firebase-tools package MUST be version 10.2.0 or newer
  • You are not using any reserved name or prefix for the environment variables’ names

In my experience, the third case is the most common source of issues with the environment variables in Firebase Functions and not easy to detect.

Reserved env variables: https://firebase.google.com/docs/functions/config-env#reserved-names

moved .env file to main root directory of the project instead of functions folder and it worked fine right after.

Experiencing this exact same issue. Migrated to .env variable from functions.config method. When starting emulators it prompts for default values in the terminal even when a default is in the code.

I was running into this issue as well, and tried a lot of things in this thread. The final step that helped me was upgrading firebase-tools.

$ npm install -g firebase-tools@latest
$ firebase --version
11.25.2

For good measure, I’m also using dotenv like @matometaru suggested.

import dotenv from 'dotenv';
dotenv.config();

Now, firebase emulators:start and firebase functions:shell both are able to pick up the local config from .env.local

i  functions: Loaded environment variables from .env.local

@litehacker did something similar to what I described in the last comment work for you? As it is still not working for me.

@taeold do you probably have any more insights based on the details I provided in my last comment?

@taeold thanks for the fix, now at least the log shows it picks up the file: i functions: Loaded environment variables from .env, .env.default, .env.local.

Unfortunately, when using within function execution code, the values from the .env.local are still not populated when using firebase-tools 11.22.0.

Following setup: .env.local:

# .env.local file contains environment variables for the Functions Emulator.
FUNCTIONS_EMULATOR=true

.env.:

.env.default:

SOME_OTHER_VAR=false

Now, having a file environment.ts

const environmentVariable_FunctionsEmulator = defineBoolean('FUNCTIONS_EMULATOR')

export function isRunningInEmulator(): boolean {
  console.log(`Process env: ${process.env.FUNCTIONS_EMULATOR}`)
  console.log(`defineBoolean: ${environmentVariable_FunctionsEmulator.value()}`)
  return environmentVariable_FunctionsEmulator.value() === true
}

When calling isRunningInEmulator() from a function execution code and running the code in the emulator using firebase emulators:exec, it always logs

Process env: undefined
defineBoolean: false

even though in the .env.local file, it is defined as true.