| name | tauri-dotenv-working-directory |
| description | Fix for Tauri app not loading .env file with dotenvy. Use when: (1) Environment
variables return "not set" errors in Tauri commands, (2) dotenvy::from_filename()
fails with relative paths like "../../.env", (3) API keys or config work locally
but not in Tauri app, (4) GhostClient::from_env() or similar fails with missing
env vars. The fix is that `cargo tauri dev` runs with CWD at project root, not
at ui/src-tauri, so use ".env" not "../../.env".
|
| author | Claude Code |
| version | 1.0.0 |
| date | "2025-01-23T00:00:00.000Z" |
Tauri Dotenvy Working Directory Fix
Problem
When adding dotenvy to a Tauri app to load environment variables, relative paths
like ../../.env fail because the working directory during cargo tauri dev is
not what you'd expect from the file structure.
Context / Trigger Conditions
Error symptoms:
GHOST_URL not set or similar "env var not set" errors
GhostClient::from_env() or API clients fail to initialize
dotenvy::from_filename("../../.env") returns Err
- App works when env vars are exported manually but not via .env
Project structure:
project-root/
├── .env # Environment file here
├── Cargo.toml
├── crates/
└── ui/
├── src/
└── src-tauri/
├── Cargo.toml
└── src/
└── main.rs # dotenvy loaded here
Assumption (wrong):
Since main.rs is in ui/src-tauri/src/, you might think CWD is ui/src-tauri/
and use ../../.env to reach the project root.
Reality:
When cargo tauri dev runs, the working directory is the project root, not
ui/src-tauri/. So the path should just be .env.
Solution
Try multiple paths to handle different execution contexts:
fn main() {
let env_paths = [
".env",
"../../.env",
"../.env",
];
let mut loaded = false;
for path in &env_paths {
if dotenvy::from_filename(path).is_ok() {
eprintln!("Loaded .env from: {}", path);
loaded = true;
break;
}
}
if !loaded {
eprintln!("Warning: Could not load .env file from any location");
}
tauri::Builder::default()
}
Cargo.toml dependency:
[dependencies]
dotenvy = "0.15"
Verification
-
Add logging to see which path works:
eprintln!("Loaded .env from: {}", path);
-
Check the Tauri dev output for the message:
Loaded .env from: .env
-
Verify env vars are available:
println!("GHOST_URL = {:?}", std::env::var("GHOST_URL"));
Example
Before (fails):
fn main() {
if let Err(e) = dotenvy::from_filename("../../.env") {
eprintln!("Warning: Could not load .env: {}", e);
}
}
After (works):
fn main() {
if let Err(e) = dotenvy::from_filename(".env") {
eprintln!("Warning: Could not load .env: {}", e);
}
}
Notes
- The working directory behavior is determined by how Tauri's dev command runs cargo
- In production builds, the working directory may be different (app installation dir)
- For production, consider embedding secrets differently or using a config file
- The multi-path approach handles both dev and various execution scenarios
- Always log which path was loaded to aid debugging
Related
- Tauri doesn't automatically load .env files - you must add dotenvy yourself
- This issue is separate from Tauri IPC (which only works in the webview)
- Environment variables set in the shell will override .env file values