usebruno/bruno · error · Error
Invalid .env filename
Error message
Invalid .env filename
What it means
Thrown by 'renderer:save-dotenv-variables' when isValidDotEnvFilename(filename) returns false. That validator requires filename to be exactly '.env' or to match /^\.env\.[a-zA-Z0-9._-]+$/, with no path separators (basename must equal the whole input). The default filename parameter is '.env'.
Source
Thrown at packages/bruno-electron/src/ipc/collection.js:858
const format = getCollectionFormat(collectionPathname);
const envFilePath = resolveEnvironmentFilePath(collectionPathname, environmentName, format);
if (!fs.existsSync(envFilePath)) {
throw new Error(`environment: ${envFilePath} does not exist`);
}
fs.unlinkSync(envFilePath);
environmentSecretsStore.deleteEnvironment(collectionPathname, environmentName);
} catch (error) {
return Promise.reject(error);
}
});
// Save .env file variables for collection
ipcMain.handle('renderer:save-dotenv-variables', async (event, collectionPathname, variables, filename = '.env') => {
try {
if (!isValidDotEnvFilename(filename)) {
throw new Error('Invalid .env filename');
}
validatePathIsInsideCollection(collectionPathname);
const dotEnvPath = path.join(collectionPathname, filename);
const content = utils.jsonToDotenv(variables);
await writeFile(dotEnvPath, content);
return { success: true };
} catch (error) {
console.error('Error saving .env file:', error);
return Promise.reject(error);
}
});
// Save .env file raw content for collection
ipcMain.handle('renderer:save-dotenv-raw', async (event, collectionPathname, content, filename = '.env') => {
try {View on GitHub (pinned to 9bdd81c7bd)
Solutions
- Pass only '.env' or a string matching /^\.env\.[a-zA-Z0-9._-]+$/ (e.g. '.env.production').
- If the caller has a profile name like 'production', send filename as `.env.${profile}`.
- Run isValidDotEnvFilename on the caller side before invoking the IPC.
Example fix
// before
await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, 'production');
// after
const filename = profile ? `.env.${profile}` : '.env';
if (!/^\.env(\.[a-zA-Z0-9._-]+)?$/.test(filename)) throw new Error('bad dotenv filename');
await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, filename); Defensive patterns
Strategy: validation
Validate before calling
// Replicates isValidDotEnvFilename (filesystem.js:520)
function isValidDotEnvFilename(filename) {
if (!filename || typeof filename !== 'string') return false;
const basename = path.basename(filename);
if (basename !== filename) return false;
return basename === '.env' || (basename.startsWith('.env.') && /^\.env\.[a-zA-Z0-9._-]+$/.test(basename));
}
if (!isValidDotEnvFilename(filename)) throw new Error('invalid dotenv filename'); Type guard
function isDotEnvFilename(filename) {
return typeof filename === 'string'
&& path.basename(filename) === filename
&& (filename === '.env' || /^\.env\.[a-zA-Z0-9._-]+$/.test(filename));
} Try / catch
try {
await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, filename);
} catch (e) {
if (/Invalid \.env filename/.test(e.message)) {
filename = filename.startsWith('.env') ? filename : `.env.${filename}`;
await window.ipcRenderer.invoke('renderer:save-dotenv-variables', collectionPath, vars, filename);
} else throw e;
} Prevention
- Always pass '.env' or '.env.<profile>' with profile chars limited to [A-Za-z0-9._-].
- Map UI profile labels to '.env.<label>' at the call boundary, never send the bare label.
- Never allow path separators in the dotenv filename (blocked by the basename check).
When it happens
Trigger: Passing a filename like 'env', '.env/extra', 'prod.env', '.Env', '../.env', or any name not starting with '.env'. Passing undefined/null or a path with directory separators.
Common situations: Frontend sends the bare profile name instead of '.env.<profile>'. User types a custom dotenv filename that doesn't follow the .env* convention. Path traversal attempt blocked by the basename check.
Related errors
- ${filename} file already exists
- ${request.filename} is not a valid filename
- Could not determine collection for target directory
- A file with the name "${finalFilename}" already exists in th
- Invalid scope type: ${scopeType}
AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13).
Data as JSON: /api/errors/0d805fa035d29bb9.
Report an issue: GitHub.