"Successful deletion with Express, yet error message of 'Not Found' displayed

I've implemented this boilerplate to build my API, utilizing express and typeorm with typescript.

When attempting to delete a question, the deletion process works smoothly but I receive a 404 not found response.

Below is my Question.ts class:

@Entity()
export class Question extends BaseEntity {

    @PrimaryColumn('uuid')
    public id: string;

    @IsNotEmpty()
    @Column()
    public title: string;

    @IsNotEmpty()
    @Column({
        length: 2000,
    })
    public description: string;

    @IsNotEmpty()
    @Column()
    public answered: boolean;

    @ManyToOne(type => User, user => user.questions, { onDelete: 'SET NULL', onUpdate: 'CASCADE' })
    public user: User;

    @IsNotEmpty()
    @ManyToMany(type => Tag)
    @JoinTable()
    public tags: Tag[];

    @OneToMany(type => Answer, answer => answer.question)
    public answers: Answer[];

    @OneToMany(type => Comment, comment => comment.question)
    public comments: Comment[];
}

This is the request method in the controller:

@Delete('/:id')
public delete(@Param('id') id: string): Promise<void> {
    return this.questionService.delete(id);
}

And here's the corresponding method in the service:

public async delete(id: string): Promise<void> {
    this.log.info('Deleting question: ', id);
    try {
        await Question.delete(id);
    } catch (error) {
        this.log.error('Failed to delete question: ', id, ' Error message: ', error);
    }
}

Despite the successful deletion of the question, a 404 error is being returned. Any insights on why this discrepancy occurs?

Update

Upon request, here is the complete file of the controller:

import { Request } from 'express';
import {
    Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam, Req
} from 'routing-controllers';
import { ResponseSchema } from 'routing-controllers-openapi';

import { QuestionNotFoundError } from '../errors/QuestionNotFoundError';
import { Answer, Comment, PagedResult, Question, Tag, User } from '../models/Models';
import { QuestionService } from '../services/Services';
import { CreateQuestionBody } from './Bodies/CreateQuestionBody';
import { PutQuestionBody } from './Bodies/PutQuestionBody';
import { QuestionResponse } from './responses/Responses';

@JsonController('/questions')
export class QuestionController {
    constructor(
        private questionService: QuestionService
    ) { }

    @Get()
    // tslint:disable-next-line:max-line-length
    public async find(@Req() req: Request, @QueryParam('skip') skip: number, @QueryParam('take') take: number, @QueryParam('orderBy') orderBy: string, @QueryParam('where') where: string): Promise<PagedResult<Question>> {
        const questions = await this.questionService.find();

        return new PagedResult<Question>().Create(req, questions, skip, take, orderBy, where);
    }

    @Get('/:id')
    @ResponseSchema(QuestionResponse)
    @OnUndefined(QuestionNotFoundError)
    public findOne(@Param('id') id: string): Promise<Question | undefined> {
        return this.questionService.findOne(id);
    }

    ...
    
    // More controller methods can be added here
    
    ...

    @Delete('/:id')
    public delete(@Param('id') id: string): Promise<void> {
        return this.questionService.delete(id);
    }
}

Answer №1

After reviewing the error logs you provided, it appears that the source of the error is within the ExpressDriver.ts file. Upon further inspection of the file on github, I identified the specific logic causing the issue.

https://i.sstatic.net/0jgQg.png

It seems that when the result returned is undefined and no undefinedResultCode is specified, a NotFoundError() is triggered, resulting in a 404 status code.

To address this issue, consider returning a response from the function or include

@UndefinedResultCode(200)

at the beginning of the delete function.

Answer №2

It appears that your questionService.delete(id) method is not returning any value. As a result, the delete handler is returning undefined, causing Express to believe that the endpoint is unhandled and therefore returning a 404 error. To resolve this issue, make sure to return a value from your questionService like so:

try {
  await Question.delete(id);
  return 'OK' // add this
} catch (error) {
  this.log.error('Could not delete question: ', id, ' Message: ', error);
}

You can also opt to force an empty response (HTTP 204) in the delete route handler.

Answer №3

After encountering an issue, @Jerin D Joy played a vital role in guiding me towards a solution. Utilizing routing-controllers in the boilerplate piqued my interest. Upon inspecting the options class within the repository, I discovered the ability to customize the default response code for undefined returns. By default, this is set to 404, but I successfully altered it to 200 with some minor adjustments. The current configuration now resembles:

const app: Application = createExpressServer({
  cors: true,
  routePrefix: env.app.routePrefix,
  controllers: env.app.dirs.controllers,
  middlewares: env.app.dirs.middlewares,
  classTransformer: true,
  authorizationChecker: authorizationChecker(connection),
  currentUserChecker: currentUserChecker(connection),
  defaults: {
    undefinedResultCode: 200,
  },
});

This solution effectively addresses my initial problem as it allows me to specify a custom error for undefined responses. Simply removing the @OnUndefined decorator from delete requests streamlines the process.

Note: During implementation, I did have to make adjustments to certain requests, so if adopting this approach, ensure you assess which requests require modification.

Note2: While returning a string like Successfully deleted object could resolve the issue, I personally advocate for the aforementioned method as I believe it aligns better with best practices.

Answer №4

@Delete('/:id')
public remove(@Param('id') id: string): Promise<void> {
    return await this.questionService.remove(id);
}

Using an asynchronous function without proper handling could lead to receiving a <pending> object, potentially causing issues.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Leveraging Handlebars for templating in Node.js to incorporate a customized layout

app.js const exphbs = require('express-handlebars'); app.engine('handlebars', exphbs({defaultLayout: 'layout'})); app.set('view engine', 'handlebars'); app.use('/catalog', require('./routes/ ...

The parameters 'event' and 'payload' do not match in type

Upon running the build command, I encountered a type error that states: Type error: Type '(event: React.FormEvent) => void' is not assignable to type 'FormSubmitHandler'. Types of parameters 'event' and 'payload&apos ...

The data in MongoDB is organized using unique identifiers called ObjectId

I am currently working on a MEAN Crud project and encountering some issues. Despite the data being received in the mongodb, it is displaying as an objectId instead of the actual content. You can see this issue in the image below: https://i.stack.imgur.com ...

Is it possible to apply a formatting filter or pipe dynamically within an *ngFor loop in Angular (versions 2 and 4

Here is the data Object within my component sampleData=[ { "value": "sample value with no formatter", "formatter": null, }, { "value": "1234.5678", "formatter": "number:'3.5-5'", }, { "value": "1.3495", "formatt ...

Can you explain the step-by-step process of how an await/async program runs in TypeScript/JavaScript or Python?

As a C++ developer specializing in multithreading, I've been diving into the intricacies of async/await. It's been a challenge for me as these concepts differ from how C++ programs are typically executed. I grasp the concept of Promise objects, ...

Is it possible to transform a reference to a React Component into JSON format?

I am looking to serialize the state of a React component into JSON format and save it in a database. Here is the current structure of my code: const [exampleState, setExampleState] = useState([ { componentName: "Test component", co ...

Learn the process of transmitting JSON data from a server-side (nodejs) to the client-side using Ajax

I have successfully set up a Node.js/express server to make a GET call to an API, which returns JSON data. Now, I am looking for ways to send this JSON data to my local JavaScript (client-server) in order to manipulate it by looping through and appending i ...

Create allowances for specific areas

One of my methods involves the saving of an author using the .findOneAndUpdate function. The structure of AuthorInterface is as follows: export interface AuthorInterface { name: string, bio: string, githubLink: string, ...

Encountering a Nextjs hydration issue after switching languages

I am facing an issue with my Next.js project using version v12.2.4 and implementing internationalization with i18next. The project supports two languages: Italian and English. Strangely, when I switch to English language, the app throws errors, while every ...

Sending an ID from an array within a *ngFor loop to a different component in Angular: a step-by-step guide

I have a collection of items that I loop through using ngFor. My goal is to pass all its attributes to another component. I attempted to accomplish this with the following code: *ngFor='let item of postList [routerLink]="['/detailed-post&ap ...

Initiating a request to a server located remotely

Having an issue trying to proxy a request from my angular client app using express.js as middleware. app.use('/v1', function(req, res) { var url = process.env.API_URL + req.url; console.info('Proxing to: ', url); var r = null; ...

What is the best way to save user session variables in a MEAN.JS application?

I have chosen to utilize MEAN.JS for my project. I need to save a parameter for each user throughout their session on the website (from when they first open the site until they close their browser, even if they do not log in). This parameter should be ac ...

What causes the typescript error in my code: The argument being passed is either a string, an array of FilterData, an array of numbers, or an array of Moments, which is not compatible with a parameter of type 'string'?

When writing my code, I have the need to utilize various types for different scenarios. Depending on the situation, the type may be a string, number[], FilterData[] (a custom type), or Moment[]. To address this requirement, I defined the type as: export ty ...

Can you explain how to incorporate a node module script into a React.js project?

I have encountered an issue where the element works perfectly fine when using an external node module, but fails to function properly when using a locally downloaded node module. Unfortunately, I am unable to identify the root cause of this problem. You c ...

Certain public files in Express cannot be accessed locally

While running my Node.js application on localhost, I am able to access http://localhost:3000/css/dashboard.css without any issues. However, when attempting to access http://localhost:3000/css/logo.png for a logo image in the same directory, all I receive i ...

Tips on how to send Mongoose response variable in NodeJS Express router res.render?

I just finished setting up a basic Express NodeJS server. My goal is to save the value of the setting returned from mongoose.find() as a variable in res.render, but every time I try, it throws an error saying Cannot read property of undefined. Here' ...

JSON data causing MySQL error while processing multiple rows

I'm attempting to execute a multiple row update in my database. It works flawlessly when updating just one row, but I encounter syntax errors when trying to update multiple rows at once. I have ensured that the configuration is set correctly with { .. ...

Utilizing conditional types for type narrowing within a function's body: A comprehensive guide

I created a conditional type in my code that constrains the second argument of my class constructor based on the type of the first argument. Although the type checker correctly limits what I can pass to the constructor, I am struggling to get the compiler ...

Using NgModel with a custom element

I am currently using a basic component within my form as shown below: <app-slider [min]="field.min" [max]="field.max" [value]="field.min"></app-slider> This component consists of the following code: HTML: <input #mySlider class="s ...

The option value in mat-autocomplete is not displaying correctly on IOS devices

When I click on the first option in the dropdown menu, it does not display the selected option in the field. However, when I select the second option, then the value of the first option appears, and when I choose the third option, the value of the second o ...