Unable to findOne record while it can find ALL records

System Information
  • Strapi Version: 5.0.2 Community
  • Operating System: Windows 11 Enterprise Version 23H2 (OS Build 22631.4169)
  • Database: sqlite
  • Node Version: 18.20.4
  • NPM Version: 10.8.3
  • Yarn Version: –

I created a Gift collection type with 3 data fields, they are Name, Description and Quantity. I entered a new record entry, published the record, and granted the find and findOne permission to the Public role.

I am able to get ALL records by following URL
localhost:1337/api/gifts/

The output:

{
    "data": [
        {
            "id": 2,
            "documentId": "bagsmgefw9wsmxe4po9qx47v",
            "Name": "Moutai Spirit",
            "Description": [
                {
                    "type": "paragraph",
                    "children": [
                        {
                            "type": "text",
                            "text": "Moutai (simplified Chinese: 茅台; traditional Chinese: 茅臺; pinyin: máotái) is a style of baijiu made in the town of Maotai, Guizhou Province, China. Maotai is made from sorghum, a wheat based qū, and water from the Chishui River, and it uses traditional Chinese techniques of fermentation, distillation, and aging, to produce a spirit with a nutty, grain forward and savory aroma and flavor."
                        }
                    ]
                }
            ],
            "Quantity": 100,
            "createdAt": "2024-10-03T11:32:21.057Z",
            "updatedAt": "2024-10-03T11:32:21.057Z",
            "publishedAt": "2024-10-03T11:32:21.069Z",
            "locale": null
        }
    ],
    "meta": {
        "pagination": {
            "page": 1,
            "pageSize": 25,
            "pageCount": 1,
            "total": 1
        }
    }
}

However, I am not able to find that single record by ID, it returns 404 not found error.

localhost:1337/api/gifts/2

{
    "data": null,
    "error": {
        "status": 404,
        "name": "NotFoundError",
        "message": "Not Found",
        "details": {}
    }
}

also tried to use different ID, /api/gifts/1, /api/gifts/3 or use singular noun /api/gift/2, it still doesn’t work

The record in the database is as below, i.e. record ID 2 is published

I have no customization to this Gift collection type.

The controller of the Gift collection ./src/api/gift/controllers/gift.ts is as below:

/**
 * gift controller
 */

import { factories } from '@strapi/strapi'

export default factories.createCoreController('api::gift.gift');

Do I miss any step before I can find individual record?

it works on documentID
localhost:1337/api/gifts/bagsmgefw9wsmxe4po9qx47v

    import { factories } from '@strapi/strapi';
    
    export default factories.createCoreRouter('api::author.author');

Suppose the CoreRouter will generate routes for these actions:

  • GET /authors (find all authors)
  • GET /authors/:id (find one author)
  • POST /authors (create a new author)
  • PUT /authors/:id (update an author)
  • DELETE /authors/:id (delete an author)

However, it seems find one author is not enabled by default.


/**
 * author router.
 * .\src\api\author\routes\author.ts
 */

// Core Router
//import { factories } from '@strapi/strapi';
//export default factories.createCoreRouter('api::author.author');


export default {
  routes: [
    {
      method: 'GET',
      path: '/authors',
      handler: 'api::author.author.find',
      config: {
        auth: false,
      },
    },
    {
      method: 'POST',
      path: '/authors',
      handler: 'api::author.author.create',
      config: {
        auth: false,
      },
    },
    {
      method: 'PUT',
      path: '/authors/:id',
      handler: 'api::author.author.update',
      config: {
        auth: false,
      },
    },
    {
      method: 'DELETE',
      path: '/authors/:id',
      handler: 'api::author.author.delete',
      config: {
        auth: false,
      },
    },
    {
      method: 'GET',
      path: '/authors/:id',
      handler: 'api::author.author.findOne',
      config: {
        auth: false,
      },
    },
  ],
};
/**
 *  author controller
 *  .\src\api\author\controllers\author.ts
 */

import { factories } from '@strapi/strapi';

export default factories.createCoreController('api::author.author', ({ strapi }) => ({
  // Customize the findOne method
  async findOne(ctx) {
    const { id } = ctx.params;

    // Ensure the ID is numeric
    const authorId = parseInt(id, 10);
    if (isNaN(authorId)) {
      return ctx.badRequest('Invalid ID format');
    }

    // Fetch the author by ID using Strapi's db query API
    const author = await strapi.db.query('api::author.author').findOne({
      where: { id: authorId },
      populate: ['books'], // Populate related data if needed
    });

    if (!author) {
      return ctx.notFound('Author not found');
    }

    //return author;
        
    // You can add more custom logic here if needed
    // sanitizeOutput - exclude private fields from the response
    // This will prevent sensitive fields, like password, from being exposed in the response 
    const sanitizedEntity = await this.sanitizeOutput(author, ctx);
    return this.transformResponse(sanitizedEntity);
  },
}));

I use custom-route and controller to solve this issue. If you have any better way to solve it, please let me know.