{"record":{"id":"391bacbb3fdb32bf","repo":"usebruno/bruno","slug":"export-path-must-be-an-absolute-directory-path","errorCode":null,"errorMessage":"Export path must be an absolute directory path","messagePattern":"Export path must be an absolute directory path","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-electron/src/ipc/collection.js","lineNumber":966,"sourceCode":"      }\n\n      await withFileLock(envFilePath, async () => {\n        const fileContent = fs.readFileSync(envFilePath, 'utf8');\n        const environment = parseEnvironment(fileContent, { format });\n        environment.color = color;\n        const updatedContent = stringifyEnvironment(environment, { format });\n        await writeFile(envFilePath, updatedContent);\n      });\n    } catch (error) {\n      return Promise.reject(error);\n    }\n  });\n\n  // Generic environment export handler\n  ipcMain.handle('renderer:export-environment', async (event, { environments, environmentType, filePath, exportFormat = 'folder' }) => {\n    try {\n      if (!filePath || typeof filePath !== 'string' || !path.isAbsolute(filePath)) {\n        throw new Error('Export path must be an absolute directory path');\n      }\n      if (!fs.existsSync(filePath) || !isDirectory(filePath)) {\n        throw new Error(`Export path: ${filePath} is not an existing directory`);\n      }\n      if (environmentType !== 'collection' && environmentType !== 'global') {\n        throw new Error(`Unsupported environment type: ${environmentType}`);\n      }\n\n      const { app } = require('electron');\n      const appVersion = app?.getVersion() || '2.0.0';\n\n      // For single environments and folder exports, include info in each environment\n      const environmentWithInfo = (environment) => ({\n        name: environment.name,\n        variables: environment.variables,\n        color: environment.color ?? undefined,\n        info: {\n          type: 'bruno-environment',","sourceCodeStart":948,"sourceCodeEnd":984,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-electron/src/ipc/collection.js#L948-L984","documentation":"Thrown by 'renderer:export-environment' when the supplied filePath is falsy, not a string, or fails path.isAbsolute(). Bruno requires the export destination to be an absolute, user-chosen directory (typically from a native dialog.showOpenDialog result). Relative paths, undefined, or null all trip this guard before any disk access.","triggerScenarios":"Calling export-environment with filePath omitted from the payload, passed as a relative path like '../exports', or passed as a non-string (number/object). Common when the user cancels the folder picker and the dialog returns undefined/empty string but the export call still fires.","commonSituations":"Folder-picker dialog cancelled or not shown, hardcoded relative path in test/script, path stored in state as undefined after a navigation.","solutions":["Gate the export on a non-empty absolute path returned by the folder picker; abort the action when the user cancels.","Normalize user input with path.resolve() only after confirming a value exists, or require the picker result.","Add a type check in the renderer payload before invoking the IPC."],"exampleFix":"// before\nawait window.Ipc.invoke('renderer:export-environment', { environments, environmentType, filePath: inputRef.current.value });\n\n// after\nconst filePath = await window.ipc.invoke('main:select-folder');\nif (!filePath) return; // user cancelled\nawait window.Ipc.invoke('renderer:export-environment', { environments, environmentType, filePath });","handlingStrategy":"validation","validationCode":"function isValidExportPath(p: unknown): boolean {\n  return typeof p === 'string' && p.length > 0 && path.isAbsolute(p);\n}\nif (!isValidExportPath(filePath)) {\n  throw new Error('An absolute export directory is required');\n}","typeGuard":"function isAbsoluteDirPath(p: unknown): p is string {\n  return typeof p === 'string' && p.length > 0 && path.isAbsolute(p);\n}","tryCatchPattern":"try {\n  await window.Ipc.invoke('renderer:export-environment', payload);\n} catch (e) {\n  if (String(e?.message).includes('absolute directory path')) {\n    const picked = await pickFolder(); if (!picked) return;\n    payload.filePath = picked;\n    await window.Ipc.invoke('renderer:export-environment', payload);\n  } else throw e;\n}","preventionTips":["Always source filePath from a native folder picker.","Abort the export when the picker is cancelled.","Type-check the payload before invoking."],"tags":["ipc","export","path-validation","electron","environment"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}