Error when trying to create a simple custom route: Error creating endpoint GET<route>: Cannot read property <controller function> of undefined

System Information
  • Strapi Version: V4
  • Operating System: aws linux AMI
  • Database: mysql
  • Node Version: 14.18.1
  • NPM Version: 6.14.15

I am trying to get the example code from the docs “Development/Back-end customization” to run for a simple custom route “/api/customizeUser/…”.

My folder structure:
folderstructure

My files content:

// api/customizeUser/routes/customizeUser
module.exports = {
  routes: [
    { // Path defined with a URL parameter
      method: 'GET',
      path: '/customizeUser',
      handler: 'customizeUser.index',
      // }
    }
  ]
}

// api/customizeUser/controllers/customizeUser
module.exports = {
  async index(ctx, next) {
    ctx.body = 'Hello World!'; // we could also send a JSON
  },
};

When i try to start the server with npm run develop the server crashes with the following error:

error: Error creating endpoint GET /customizeUser: Cannot read property ‘index’ of undefined
TypeError: Error creating endpoint GET /customizeUser: Cannot read property ‘index’ of undefined

What am i missing?

Hey there @dmuellner , did you ever figure out the answer to this question?

I ran into this and discovered that you can’t use camel-casing, like “customizeUser”. It has to be “customize-user”. The generate command line tool really should restrict this at the point of creation, since it already restricts other characters like “_”.

7 Likes

Excellent, you just saved me lots of time! This was indeed the issue!

I renamed my controller js file from customControlle.js to custom-controller.js and it worked like a charm! :sparkles:

Strapi V4 really needs to document this thing. I had been scratching my head regarding this for quite some time today and I looked everywhere but couldn’t find a place where Strapi v4 docs explicitly mention the casing to be kebab-case instead of camelCase.

1 Like

I had a similar problem and it was not related to the camelCase. That’s why I thought to put it here thinking that it might be helpful for someone in future.

In my case, accidentally i was doing array destructuring

const [ licenseKey ] = ctx.request.body;

instead of object descrtucuring

const { licenseKey } = ctx.request.body;

Happy debugging :slight_smile:

PLEASE HELP!

I’m encountering this issue with my custom plugin. The error code is:

TypeError: Error creating endpoint GET /pass-data: Cannot read properties of undefined (reading 'index')

PLEASE NOTE: I already followed the steps mentioned on the previous posts on this page and I double-checked that I have my setup correct. I also reference the normal API route/controller setup. I’m not sure why the controller in the custom plugin is not being reached.

  • Strapi Version: 4.24.0

I used the workspaces to handle the custom plugin in my main package.json file:

{
  "name": "ciscal-blogs",
  "private": true,
  "version": "0.1.0",
  "description": "A Strapi application",
  "workspaces": ["./src/plugins/slugger"],
  "scripts": {
    "develop": "strapi develop",
    "start": "strapi start",
    "build": "strapi build",
    "strapi": "strapi"
  },
  "dependencies": {
    "@strapi/plugin-cloud": "4.24.0",
    "@strapi/plugin-i18n": "^4.24.0",
    "@strapi/plugin-seo": "^1.9.8",
    "@strapi/plugin-users-permissions": "4.24.0",
    "@strapi/strapi": "4.24.0",
    "mysql": "2.18.1",
    "mysql2": "^3.9.7",
    "react": "^18.0.0",
    "react-dom": "^18.0.0",
    "react-router-dom": "5.3.4",
    "styled-components": "5.3.3"
  },
  "author": {
    "name": "A Strapi developer"
  },
  "strapi": {
    "uuid": "f8a560fb-37c0-4842-b366-5243cb65fefa"
  },
  "engines": {
    "node": ">=18.0.0 <=20.x.x",
    "npm": ">=6.0.0"
  },
  "license": "MIT"
}

Here is my dependency tree when i run npm list:

ciscal-blogs@0.1.0 C:\Users\luder\Documents\CreaxonDev\CISCALBlogs\ciscal-blogs
├── @strapi/plugin-cloud@4.24.0
├── @strapi/plugin-i18n@4.25.2
├── @strapi/plugin-seo@1.9.8
├── @strapi/plugin-users-permissions@4.24.0
├── @strapi/strapi@4.24.0
├── mysql@2.18.1
├── mysql2@3.10.2
├── react-dom@18.3.1
├── react-router-dom@5.3.4
├── react@18.3.1
├─┬ slugger@1.0.0 -> .\src\plugins\slugger
│ ├── @strapi/design-system@1.19.0
│ ├── @strapi/helper-plugin@4.25.2
│ ├── @strapi/icons@1.19.0
│ ├── prop-types@15.8.1
│ ├── react-dom@18.3.1 deduped
│ ├── react-router-dom@5.3.4 deduped
│ ├── react@18.3.1 deduped
│ ├── source-map-loader@1.1.3
│ └── styled-components@5.3.11
└── styled-components@5.3.3

in my custom plugin, i followed the steps as per the strapi documentation:

Developing Plugins > Guides:

directory: my-plugin/server/routes/index.js

module.exports = {
  'pass-data': {
    type: 'admin',
    routes: [
      {
        method: 'GET',
        path: '/pass-data',
        handler: 'myPluginContentType.index',
        config: {
          policies: [],
          auth: false,
        },
      },
    ]
  }
  // ...
};
directory: /my-plugin/server/controllers/my-plugin-content-type.js
'use strict';

module.exports = {
  async index(ctx) {
    ctx.body = 'You are in the my-plugin-content-type controller!';
  }
}
directory: /my-plugin/admin/src/api/foobar.js

import axios from 'axios';

const foobarRequests = {
  getFoobar: async () => {
    const data = await axios.get(`/my-plugin/pass-data`);
    return data;
  },
};
export default foobarRequests;
directory: /my-plugin/admin/src/components/MyComponent/index.js
import foobarRequests from "../../api/foobar";
const [foobar, setFoobar] = useState([]);

// …
useEffect(() => {
  foobarRequests.getFoobar().then(res => {
    setSchemas(res.data); // im confused about this from the docs. this is not existing anywhere in the steps. 
  });
}, [setFoobar]);
// …