tsoa icon indicating copy to clipboard operation
tsoa copied to clipboard

tsoa crashes due to missing check in `prettyTroubleCause`

Open CodeSmith32 opened this issue 4 months ago • 1 comments

Sorting

  • I'm submitting a ...

    • [x] bug report
    • [ ] feature request
    • [ ] support request
  • I confirm that I

    • [x] used the search to make sure that a similar issue hasn't already been submit

Expected Behavior

It doesn't crash when running it. (Our code is currently proprietary. Cannot release. Sorry.)

Current Behavior

tsoa crashes due to a missing check in prettyTroubleCause: https://github.com/lukeautry/tsoa/blob/master/packages/cli/src/metadataGeneration/exceptions.ts#L37

This happens because, even though node.pos !== -1 is true, node.parent is undefined, and node.getText() relies on parent not being undefined.

Possible Solution

Adjust the line to check that node.parent is not falsy:

name = node.pos !== -1 && node.parent ? node.getText() : ((node as any).name?.text || '<unknown name>');
//                     ^^ ^^^^^^^^^^^

Steps to Reproduce

I'm not sure I'm able to determine all conditions under which this occurs, but it appears to occur when casting to a namespaced type within an object returned by a controller method. The following minimal code appears to trip this condition:

import { Controller, Post, Route } from "tsoa";

namespace Foo {
  export interface Bar {
    x: number;
    y: number;
  }
}

@Route("/some/endpoint")
class TestController extends Controller {
  @Post("/some/endpoint")
  async someEndpoint() {
    const thing = { x: 1, y: 2 };

    return {
      thing: thing as Foo.Bar,
    };
  }
}

export const testController = new TestController();

If node.pos should always be -1 when node.parent is undefined, then this may be an error in the TypeScript engine (TypeScript v5.6.3).

Context (Environment)

Version of the library: 6.5.1 (Worked fine in 5.1.1) Version of NodeJS: v20.11.1

  • Confirm you were using yarn not npm: [ ] (Using npm)

Detailed Description

The error occurs in the typescript engine when node.getText() tries to find the highest parent that represents the source file, in order to get the whole text contents of the file. Because node.parent is undefined, it fails, as it appears to be separated from the tree.

Thus a check for node.parent resolves the issue:

name = node.pos !== -1 && node.parent ? node.getText() : ((node as any).name?.text || '<unknown name>');
//                     ^^ ^^^^^^^^^^^

With that said, the node does appear to have an original node property which is part of the tree. An alternative solution, therefore, could look like:

name = node.pos !== -1 && node.parent ? node.getText()
  : node.pos !== -1 && node.original?.parent ? node.original.getText()
  : ((node as any).name?.text || '<unknown name>');

Breaking change?

As this error is occurring only because of an attempt to generate an error message, I don't think such a change in the condition would be that crucial or breaking.

CodeSmith32 avatar Oct 16 '24 16:10 CodeSmith32