{"record":{"id":"adb150253df82e23","repo":"usebruno/bruno","slug":"invalid-api-spec-name-and-path-are-required","errorCode":null,"errorMessage":"Invalid API spec: name and path are required","messagePattern":"Invalid API spec: name and path are required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-electron/src/utils/workspace-config.js","lineNumber":628,"sourceCode":"const getWorkspaceApiSpecs = (workspacePath) => {\n  const config = readWorkspaceConfig(workspacePath);\n  const specs = config.specs || [];\n\n  return specs.map((spec) => {\n    const specPath = spec.path ? posixifyPath(spec.path) : spec.path;\n    if (specPath && !path.isAbsolute(specPath)) {\n      return {\n        ...spec,\n        path: path.join(workspacePath, specPath)\n      };\n    }\n    return { ...spec, path: specPath };\n  });\n};\n\nconst addApiSpecToWorkspace = async (workspacePath, apiSpec) => {\n  if (!isValidSpecEntry(apiSpec)) {\n    throw new Error('Invalid API spec: name and path are required');\n  }\n\n  return withLock(getWorkspaceLockKey(workspacePath), async () => {\n    const config = readWorkspaceConfig(workspacePath);\n\n    if (!config.specs) {\n      config.specs = [];\n    }\n\n    const normalizedSpec = {\n      name: apiSpec.name.trim(),\n      path: makeRelativePath(workspacePath, apiSpec.path).trim()\n    };\n\n    const existingIndex = config.specs.findIndex(\n      (a) => a.name === normalizedSpec.name || (a.path && posixifyPath(a.path) === normalizedSpec.path)\n    );\n","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-electron/src/utils/workspace-config.js#L610-L646","documentation":"`addApiSpecToWorkspace` runs `isValidSpecEntry`, which (like collections) requires an object with non-empty trimmed `name` and `path` strings; otherwise it throws before the lock.","triggerScenarios":"Calling `addApiSpecToWorkspace(workspacePath, apiSpec)` where `apiSpec` is not an object or where `name`/`path` is missing, empty, or non-string.","commonSituations":"Spec-import form submitted with a blank path; programmatic caller omitted the path field; a dropped file path that resolved to empty; copy of an entry missing fields.","solutions":["Ensure `apiSpec.name` is a non-empty trimmed string.","Ensure `apiSpec.path` is a non-empty trimmed path (relative is fine — it gets `makeRelativePath`-normalized).","Validate both fields in the UI/controller before calling."],"exampleFix":"// before\nawait addApiSpecToWorkspace(wsPath, { name: 'Petstore' });\n\n// after\nawait addApiSpecToWorkspace(wsPath, { name: 'Petstore', path: '/work/ws/openapi.yml' });","handlingStrategy":"validation","validationCode":"function isValidSpecEntry(s) {\n  return !!s && typeof s === 'object'\n    && typeof s.name === 'string' && s.name.trim() !== ''\n    && typeof s.path === 'string' && s.path.trim() !== '';\n}\nif (!isValidSpecEntry(spec)) throw new Error('name and path required');","typeGuard":"function isSpecEntry(s: unknown): s is { name: string; path: string } {\n  if (!s || typeof s !== 'object') return false;\n  const o = s as any;\n  return typeof o.name === 'string' && o.name.trim() !== ''\n      && typeof o.path === 'string' && o.path.trim() !== '';\n}","tryCatchPattern":null,"preventionTips":["Resolve the file path from the picker before building the entry.","Disable the add button until name and path are both filled."],"tags":["workspace","api-spec","validation","config"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}