Smart Action fails with Internal Server Error

This is a template you can use to report issues. You can also drag images, videos and include Preformatted text

Expected behavior

When I click on a smart action, I expected this one to run “or at least trigger the backend endpoint”

Actual behavior

I keep on getting HttpError: HTTP Error 500: Internal Server Error:
I don’t even reach my backend code… it’s really weird. All my actions are failing…

.forestadmin-schema.json

"actions": [
        {
          "name": "My Action",
          "type": "global",
          "baseUrl": null,
          "endpoint": "/forest/actions/my-collection/my-action",
          "httpMethod": "POST",
          "redirect": null,
          "download": false,
          "fields": [],
          "hooks": {
            "load": false,
            "change": []
          }
        }]

routes/my-collection.ts

// Runs a certain smart action
router.post('/actions/my-collection/my-action', permissionMiddlewareCreator.smartAction(), (request, response) => {
    // Learn what this route does here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/routes/default-routes#delete-a-list-of-records
 console.log("hello")
  next();
});

forest/my-collection.ts

actions: [{
        name: 'My Action',
        endpoint: '/forest/actions/my-collection/my-action',
        httpMethod: 'POST',
        type: 'global'
    }]

Failure Logs

I don’t have logs within IntelliJ, but i got some in the google chrome console:

chunk.7.3063f605868b6fe645c9.js:353 POST http://localhost:3310/forest/actions/my-collection/my-action?timezone=Europe%2FParis 500 (Internal Server Error)
(anonymous) @ chunk.7.3063f605868b6fe645c9.js:353
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:21590
l @ appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1
(anonymous) @ appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1
(anonymous) @ appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1
d @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:21569
a @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:21598
Promise.then (async)
d @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:21569
a @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:21598
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:21598
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:21597
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:21599
t @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:21586
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22430
l @ appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1
(anonymous) @ appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1
(anonymous) @ appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1
u @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22409
a @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22411
Promise.then (async)
u @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22409
a @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22411
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22411
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22410
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22431
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22037
l @ appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1
(anonymous) @ appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1
(anonymous) @ appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1
O @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22007
a @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22009
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22009
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22008
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22038
(anonymous) @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22083
Promise.then (async)
value @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22083
value @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:22073
triggerCustomAction @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:1779
A @ vendor-5274ce00880a892114c98442cc88aca6.js:3143
c.triggerEvent @ vendor-5274ce00880a892114c98442cc88aca6.js:3073
n.trigger @ vendor-5274ce00880a892114c98442cc88aca6.js:5740
s.send @ vendor-5274ce00880a892114c98442cc88aca6.js:3099
send @ vendor-5274ce00880a892114c98442cc88aca6.js:3254
value @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:19174
value @ client-eb071c47afc283a9269e0b7ef1f0b9b3.js:6616
(anonymous) @ vendor-5274ce00880a892114c98442cc88aca6.js:2259
r @ chunk.7.3063f605868b6fe645c9.js:318
chunk.7.3063f605868b6fe645c9.js:325 HttpError: HTTP Error 500: Internal Server Error
    at client-eb071c47afc283a9269e0b7ef1f0b9b3.js:23829
    at l (appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1)
    at Generator._invoke (appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1)
    at Generator.next (appcues.main.83fbeef7bf4ee67f632f0e183fb2ecbd97bb7539.js:1)
    at n (client-eb071c47afc283a9269e0b7ef1f0b9b3.js:23772)
    at l (client-eb071c47afc283a9269e0b7ef1f0b9b3.js:23774)

Context

Here is my package json file

{
  "name": "my-backoffice",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node ./dist/server.js",
    "build": "rm -rf ./dist && npm run compile",
    "dev": "tsc-watch --onSuccess \"node ./dist/server.js\"",
    "compile": "tsc",
    "lint": "eslint . -c .eslintrc.json --ext .ts"
  },
  "dependencies": {
    "@google-cloud/pubsub": "^2.17.0",
    "@types/express": "^4.17.13",
    "@types/mongoose": "^5.11.97",
    "@types/node": "^16.3.3",
    "axios": "^0.21.1",
    "body-parser": "^1.19.0",
    "chalk": "~1.1.3",
    "cookie-parser": "1.4.4",
    "cors": "2.8.5",
    "debug": "~4.0.1",
    "dotenv": "~6.1.0",
    "express": "~4.17.1",
    "express-jwt": "6.0.0",
    "forest-express-mongoose": "^8.0.0",
    "mongoose": "~5.8.2",
    "morgan": "1.9.1",
    "nodemon": "^2.0.12",
    "require-all": "^3.0.0",
    "ts-node": "^10.1.0",
    "tsc-watch": "^4.4.0",
    "typescript": "^4.3.5"
  }
}

Extra note

I was developing some other parts since I upgraded my project to the latest version (and fully translated it into typescript) so I just reintegrated the smart actions and yes… I don’t know why but it’s not working at all :confused:

Thanks for any help!

Max

Hi @Emixam23 :wave:
Have you got any details on the network tab?
Please, can you share with us the preview of the response coming from the falling HTTTP request?
Like this :point_down:

Hello :slight_smile:

It was saying something like failed to evaluate permissions as far as I remember (after I created this topic I kept on trying/looking around, sorry if I haven’t posted this part)

Thanks,

Max

Hey again!

Found a related topic: Smart actions not working anymore after upgrade to v8 - #3 by Vincent_Francois

I am going to check it and get back to you if it fix my issue :slight_smile:

Best,

Max

1 Like

Hey!

I took a look at it during my launch break and… well in typescript the provided « workaround/solution » can’t work as it won’t compile…

Thanks,

Best :slight_smile:

Max

We recently fix an issue looks like this, have you try install the last version of forest-express-mongoose?

"forest-express-mongoose": "8.3.0"

let me know

Hey!

Upgrading from ‘8.0.0’ to ‘8.3.0’ fixed the issue :slight_smile: IN LOCAL

If I deploy my backoffice to the cloud… I get a new error:

Access to fetch at 'https://xxxx.herokuapp.com/forest/actions/my-collection/my-action?timezone=Europe%2FParis' from origin 'https://app.forestadmin.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Yes, my env var CORS_ORIGINS=https://app.forestadmin.com beause for other purpose, I do API request and I need to set the cors. As I can’t find the way to have a control over it (using fetch or axios), i set the env and it automatically sets the header before my request get sent to my api

Also, I’d like to know, is it possible to deploy a smart action across all the collections? Like this one I am working on isn’t really related to any of my collection, but I want to be able to access it from anywhere. Even if I have only 1 piece of “real code”, I had to write a call to that piece of code across each collection, by duplicating the same routes/forest action in each of my ts files

Thanks!!

Max

Here is my app.ts (if you need it)

import * as express from 'express';
import * as requireAll from 'require-all';
import * as path from 'path';
import * as cookieParser from 'cookie-parser';
import * as bodyParser from 'body-parser';
import * as cors from 'cors';
import * as jwt from 'express-jwt';
import * as morgan from 'morgan';
import {
  errorHandler,
  ensureAuthenticated,
  PUBLIC_ROUTES,
} from 'forest-express-mongoose';

const app = express();

let allowedOrigins = [/\.forestadmin\.com$/, /localhost:\d{4}$/];

if (process.env.CORS_ORIGINS) {
  let cors_origins = (process.env.CORS_ORIGINS as string).split(',');
  for (let cors_origin of cors_origins) {
    allowedOrigins.concat(new RegExp(cors_origin));
  }
}

const corsConfig = {
  origin: allowedOrigins,
  allowedHeaders: ['Forest-Context-Url', 'Authorization', 'X-Requested-With', 'Content-Type'],
  maxAge: 86400, // NOTICE: 1 day
  credentials: true,
};

app.use(morgan('tiny'));
app.use('/forest/authentication', cors({
  ...corsConfig,
  // The null origin is sent by browsers for redirected AJAX calls
  // we need to support this in authentication routes because OIDC
  // redirects to the callback route
  origin: corsConfig.origin.concat(new RegExp('null'))
}));
app.use(cors(corsConfig));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use(jwt({
  secret: process.env.FOREST_AUTH_SECRET,
  algorithms: ['HS256'],
  credentialsRequired: false,
}));

app.use('/forest', (request, response, next) => {
  if (PUBLIC_ROUTES.includes(request.url)) {
    return next();
  }
  return ensureAuthenticated(request, response, next);
});

requireAll({
  dirname: path.join(__dirname, 'routes'),
  recursive: true,
  resolve: (Module) => app.use('/forest', Module),
});

requireAll({
  dirname: path.join(__dirname, 'middlewares'),
  recursive: true,
  resolve: (Module) => Module(app),
});

app.use(errorHandler());

//module.exports = app;
module.exports.app = app;

Note: My remote CORS_ORIGINS is equal to https://app.forestadmin.com

Hey @Emixam23 :wave: can you copy asCurl the request and try to run it inside a command line?
image
We will see if we have more insight.

Hey!

I finally found the “real” issue. Against the console logs were saying, it was all about a missing file… I wasn’t able to reproduce the issue locally but then (don’t ask me why…) I went to heroku console app to look at the logs and… MISSING FILE… So no CORS related at all… It was all about dpl for my app to be deployed to heroku that actually (in some ways) ignored some file… adding --skip-cleanup solved the issue :slight_smile:

Thanks and sorry for this non related forest admin issue :sweat_smile:

Best,

Max