Repository: usebruno/bruno

Issue:
Bruno fails to import OpenAPI spec when it is missing a title
[Jira](https://usebruno.atlassian.net/browse/BRU-1218)

### I have checked the following:

- [x] I have searched existing issues and found nothing related to my issue.

### This bug is:

- [x] making Bruno unusable for me
- [ ] slowing me down but I'm able to continue working
- [x] annoying
- [ ] this feature was working in a previous version but is broken in the current release.

### Bruno version

2.4.0

### Operating System

Windows 11

### Describe the bug

Once a user tries to create a collection by importing an OpenAPI 3.0 spec that is missing a `title` field, Bruno fails with an cryptic error message: "Import collection failed: Import collection failed". See screenshot below.

![Image](https://github.com/user-attachments/assets/52845941-1814-4d85-92dd-44e7e7a22423)

Adding the `title` field to the OpenAPI spec gets Bruno to import the collection.

It would be nice if the error message was clearer.  Bonus points if it showed exactly what failed, so that users would know what to do to fix the issue.

### .bru file to reproduce the bug

_No response_

### Screenshots/Live demo link

![Image](https://github.com/user-attachments/assets/450369e4-68f5-4887-8b26-ca75b622817d)


Discussion:
We use the title to create the collection Name maybe instead of failing we could import as an 'Untitled Collection'. 
@anusree-bruno thanks for the speedy reply.  Appreciated!

Regarding how the title is used, personally I'd prefer to get an informative error message that's actionable.  I trust Bruno to flag concrete issues with an OpenAPI spec, and I could use that feedback to address their root cause.  As it stands, printing something like "Import collection failed: Import collection failed" is the worst of both worlds.



Patch:
diff --git a/packages/bruno-converters/src/openapi/openapi-to-bruno.js b/packages/bruno-converters/src/openapi/openapi-to-bruno.js
index 293de524bd..0d177af305 100644
--- a/packages/bruno-converters/src/openapi/openapi-to-bruno.js
+++ b/packages/bruno-converters/src/openapi/openapi-to-bruno.js
@@ -364,8 +364,8 @@ export const parseOpenApiCollection = (data) => {
         return;
       }
 
-      // TODO what if info.title not defined?
-      brunoCollection.name = collectionData.info.title;
+      brunoCollection.name = collectionData.info?.title?.trim() || 'Untitled Collection';
+
       let servers = collectionData.servers || [];
 
       // Create environments based on the servers
@@ -428,8 +428,10 @@ export const parseOpenApiCollection = (data) => {
       brunoCollection.items = brunoCollectionItems;
       return brunoCollection;
     } catch (err) {
-      console.error(err);
-      throw new Error('An error occurred while parsing the OpenAPI collection');
+      if (!(err instanceof Error)) {
+        throw new Error('Unknown error');
+      }
+      throw err;
     }
 };
 
@@ -445,8 +447,11 @@ export const openApiToBruno = (openApiSpecification) => {
     const validatedCollection = validateSchema(hydratedCollection);
     return validatedCollection
   } catch (err) {
-    console.error(err);
-    throw new Error('Import collection failed');
+    console.error('Error converting OpenAPI to Bruno:', err);
+    if (!(err instanceof Error)) {
+      throw new Error('Unknown error');
+    }
+    throw err;
   }
 };
 


Test patch:
diff --git a/packages/bruno-converters/tests/openapi/openapi-to-bruno/openapi-to-bruno.spec.js b/packages/bruno-converters/tests/openapi/openapi-to-bruno/openapi-to-bruno.spec.js
index 7c2c604095..6cffe78f65 100644
--- a/packages/bruno-converters/tests/openapi/openapi-to-bruno/openapi-to-bruno.spec.js
+++ b/packages/bruno-converters/tests/openapi/openapi-to-bruno/openapi-to-bruno.spec.js
@@ -7,6 +7,108 @@ describe('openapi-collection', () => {
 
     expect(brunoCollection).toMatchObject(expectedOutput);
   });
+
+  it('trims whitespace from info.title and uses the trimmed value as the collection name', () => {
+    const openApiWithTitle = `
+openapi: '3.0.0'
+info:
+  version: '1.0.0'
+  title: '  My API  '
+paths:
+  /get:
+    get:
+      summary: 'Request'
+      operationId: 'getRequest'
+      responses:
+        '200':
+          description: 'OK'
+servers:
+  - url: 'https://example.com'
+`;
+    const result = openApiToBruno(openApiWithTitle);
+    expect(result.name).toBe('My API');
+  });
+
+  it('defaults to Untitled Collection if info.title is only whitespace', () => {
+    const openApiWithTitle = `
+openapi: '3.0.0'
+info:
+  version: '1.0.0'
+  title: '   '
+paths:
+  /get:
+    get:
+      summary: 'Request'
+      operationId: 'getRequest'
+      responses:
+        '200':
+          description: 'OK'
+servers:
+  - url: 'https://example.com'
+`;
+    const result = openApiToBruno(openApiWithTitle);
+    expect(result.name).toBe('Untitled Collection');
+  });
+
+  it('defaults to Untitled Collection if info.title is an empty string', () => {
+    const openApiWithEmptyTitle = `
+openapi: '3.0.0'
+info:
+  version: '1.0.0'
+  title: ''
+paths:
+  /get:
+    get:
+      summary: 'Request'
+      operationId: 'getRequest'
+      responses:
+        '200':
+          description: 'OK'
+servers:
+  - url: 'https://example.com'
+`;
+    const result = openApiToBruno(openApiWithEmptyTitle);
+    expect(result.name).toBe('Untitled Collection');
+  });
+
+  it('defaults to Untitled Collection if info.title is missing', () => {
+    const openApiWithoutTitle = `
+openapi: '3.0.0'
+info:
+  version: '1.0.0'
+paths:
+  /get:
+    get:
+      summary: 'Request'
+      operationId: 'getRequest'
+      responses:
+        '200':
+          description: 'OK'
+servers:
+  - url: 'https://example.com'
+`;
+    const result = openApiToBruno(openApiWithoutTitle);
+    expect(result.name).toBe('Untitled Collection');
+  });
+
+  it('defaults to Untitled Collection if info is missing entirely', () => {
+    const openApiWithMissingInfo = `
+openapi: '3.0.0'
+paths:
+  /get:
+    get:
+      summary: 'Request'
+      operationId: 'getRequest'
+      responses:
+        '200':
+          description: 'OK'
+servers:
+  - url: 'https://example.com'
+`;
+    const result = openApiToBruno(openApiWithMissingInfo);
+    expect(result.name).toBe('Untitled Collection');
+  });
+
 });
 
 const openApiCollectionString = `