Failed to modify : "Can't create more than max_prepared_stmt_count statements"

Feature(s) impacted

Edit data into Forest Admin

Observed behavior

Since few days, whatever I tried to modify into Forest Admin I’ve the issue :

update failed: Can’t create more than max_prepared_stmt_count statements (current value: 16382)

We didn’t made any modification on Forest Integration.

Failure Logs

ategorie: 1,
marque: ‘Manfrotto’,
modele: ‘Monopod MM394’,
sous_categorie: 7
}
Unhandled rejection SequelizeDatabaseError: Can’t create more than max_prepared_stmt_count statements (current value: 16382)
at Query.formatError (/data/vhosts/ForestAdmin/node_modules/sequelize/lib/dialects/mysql/query.js:243:16)
at handler (/data/vhosts/ForestAdmin/node_modules/sequelize/lib/dialects/mysql/query.js:50:23)
at Prepare.onResult (/data/vhosts/ForestAdmin/node_modules/mysql2/lib/connection.js:612:11)
at Prepare.execute (/data/vhosts/ForestAdmin/node_modules/mysql2/lib/commands/command.js:30:14)
at Connection.handlePacket (/data/vhosts/ForestAdmin/node_modules/mysql2/lib/connection.js:425:32)
at PacketParser.onPacket (/data/vhosts/ForestAdmin/node_modules/mysql2/lib/connection.js:75:12)
at PacketParser.executeStart (/data/vhosts/ForestAdmin/node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket. (/data/vhosts/ForestAdmin/node_modules/mysql2/lib/connection.js:82:25)
at Socket.emit (events.js:314:20)
at addChunk (_stream_readable.js:297:12)
at readableAddChunk (_stream_readable.js:272:9)
at Socket.Readable.push (_stream_readable.js:213:10)
at TCP.onStreamRead (internal/stream_base_commons.js:188:23)

Context

Please provide in this mandatory section, the relevant information about your configuration:

  • Project name: Lightyshare
  • Team name: Strobe Studio
  • Environment name: Production
  • Agent type & version: …

Hello @Jonathan,

Thanks for your report.

  • Ok, did you change the sequelize version you use ?

  • Can you provide the sequelizeOptions you use in your project ?

I found a thread where they modify the value maxPreparedStatements in those dialectOptions of this settings. But this solution can have an impact on the overall performance so be carefull with the value you use.

const sequelizeOptions = { 
    dialect: "postgres",
    port: mysqlPort,
    logging: sqlLogging,
    benchmark: true,
    pool: {
        min: 10,
        max: 50
    },
    dialectOptions: {
        // @see https://github.com/sequelize/sequelize/issues/8019
        decimalNumbers: true,
        maxPreparedStatements: 2500
    },
    timezone: "+00:00"
};

Let my know if it helps.

Kind regards,
Morgan

Thx @morganperre for your fast reply !
We didn’t make any backend change too, only the database content …

in package.json

...
"sequelize": "~5.15.1"

const databaseOptions = {
  logging: !process.env.NODE_ENV || process.env.NODE_ENV === 'development' ? console.log : false,
  pool: { maxConnections: 10, minConnections: 1 },
  dialectOptions: {
	},
};

I’ll try to add this dialectOptions to see if that fix the issue.

Tim

Hey @Jonathan and @Timothy_Potter

16k+ seems quite a lot of prepared statement to me :o.

Would you mind sharing the generated SQL query associated with the failing call that triggers this issue?

Thanks in advance

2 Likes

Hi @jeffladiray

I’ve got several problems with Forest Admin :

  1. Every backend change pushed to the production server doesn’t seems to appeared on Forest Admin interface (I’ve just added a new field)

  2. I don’t have any logs for the update error, only this one :

PUT /forest/fosUser/15983?timezone=Europe%2FParis 200 6985 - 61.818 ms
PUT /forest/fosUser/15983?timezone=Europe%2FParis 422 141 - 160.266 ms

Are there an other way to debug SQL ?

  1. I’ve got troubles to connect my development environment with an Unable to authenticate you error without any logs

Thanks in advance

I’ve founded !

Executing (default): SELECT `demandeLocation`.`id`, `demandeLocation`.`DateDebut` AS `dateDebut`, `demandeLocation`.`Datefin` AS `datefin`, `demandeLocation`.`PrixJour` AS `prixJour`, `demandeLocation`.`DureeReserve` AS `dureeReserve`, `demandeLocation`.`PrixTotal` AS `prixTotal`, `demandeLocation`.`StatutLocataire` AS `statutLocataire`, `demandeLocation`.`StatutProprietaire` AS `statutProprietaire`, `demandeLocation`.`caution`, `demandeLocation`.`franchise`, `demandeLocation`.`createdAt`, `demandeLocation`.`AcceptedAt` AS `acceptedAt`, `demandeLocation`.`CanceledAt` AS `canceledAt`, `demandeLocation`.`PaidAt` AS `paidAt`, `demandeLocation`.`LimitPaidAt` AS `limitPaidAt`, `demandeLocation`.`canceled`, `demandeLocation`.`blocked`, `demandeLocation`.`blockedAt`, `demandeLocation`.`outpaid`, `demandeLocation`.`endmailed`, `demandeLocation`.`termined`, `demandeLocation`.`noModalLocataire`, `demandeLocation`.`signaledLocataire`, `demandeLocation`.`signaledProprietaire`, `demandeLocation`.`noModalProprietaire`, `demandeLocation`.`numero_location` AS `numeroLocation`, `demandeLocation`.`by_code_promo` AS `byCodePromo`, `demandeLocation`.`price_before_promo` AS `priceBeforePromo`, `demandeLocation`.`has_frais_service_locataire` AS `hasFraisServiceLocataire`, `demandeLocation`.`commision_locataire` AS `commisionLocataire`, `demandeLocation`.`transfered`, `demandeLocation`.`titre_location` AS `titreLocation`, `demandeLocation`.`tauxTvaProprietaire`, `demandeLocation`.`tauxTvaFraisDeService`, `demandeLocation`.`prix_location_ht` AS `prixLocationHt`, `demandeLocation`.`prix_location_ttc` AS `prixLocationTtc`, `demandeLocation`.`frais_service_ht` AS `fraisServiceHt`, `demandeLocation`.`frais_service_ttc` AS `fraisServiceTtc`, `demandeLocation`.`prix_total_ht` AS `prixTotalHt`, `demandeLocation`.`prix_total_ttc` AS `prixTotalTtc`, `demandeLocation`.`ownerCodePromo`, `demandeLocation`.`bank_wire_id` AS `bankWireId`, `demandeLocation`.`taxEvidenceId`, `demandeLocation`.`taxEvidenceFraisDeServiceId`, `demandeLocation`.`annonce_id` AS `annonceIdKey`, `demandeLocation`.`bank_wire_id` AS `bankWireIdKey`, `demandeLocation`.`facture_locataire_id` AS `factureLocataireIdKey`, `demandeLocation`.`user_proprietaire_id` AS `userProprietaireIdKey`, `demandeLocation`.`type_annulation_id` AS `typeAnnulationIdKey`, `demandeLocation`.`user_locataire_id` AS `userLocataireIdKey`, `demandeLocation`.`facture_id` AS `factureIdKey`, `factureLocataire`.`id` AS `factureLocataire.id`, `factureLocataire`.`numero_facture_complet` AS `factureLocataire.numeroFactureComplet`, `factureLocataire`.`numero_facture` AS `factureLocataire.numeroFacture`, `factureLocataire`.`statut_user` AS `factureLocataire.statutUser`, `factureLocataire`.`created_at` AS `factureLocataire.createdAt`, `factureLocataire`.`factured_at` AS `factureLocataire.facturedAt`, `factureLocataire`.`prix_ht` AS `factureLocataire.prixHt`, `factureLocataire`.`montant_tva` AS `factureLocataire.montantTva`, `factureLocataire`.`MangoId` AS `factureLocataire.mangoId`, `factureLocataire`.`amount_ttc_quick_books_invoice` AS `factureLocataire.amountTtcQuickBooksInvoice`, `factureLocataire`.`quick_books_invoice_id` AS `factureLocataire.quickBooksInvoiceId`, `factureLocataire`.`payin_quick_books` AS `factureLocataire.payinQuickBooks`, `factureLocataire`.`lien_facture` AS `factureLocataire.lienFacture`, `userProprietaire`.`id` AS `userProprietaire.id`, `userProprietaire`.`username` AS `userProprietaire.username`, `userProprietaire`.`username_canonical` AS `userProprietaire.usernameCanonical`, `userProprietaire`.`email` AS `userProprietaire.email`, `userProprietaire`.`email_canonical` AS `userProprietaire.emailCanonical`, `userProprietaire`.`enabled` AS `userProprietaire.enabled`, `userProprietaire`.`salt` AS `userProprietaire.salt`, `userProprietaire`.`password` AS `userProprietaire.password`, `userProprietaire`.`last_login` AS `userProprietaire.lastLogin`, `userProprietaire`.`locked` AS `userProprietaire.locked`, `userProprietaire`.`expired` AS `userProprietaire.expired`, `userProprietaire`.`expires_at` AS `userProprietaire.expiresAt`, `userProprietaire`.`confirmation_token` AS `userProprietaire.confirmationToken`, `userProprietaire`.`password_requested_at` AS `userProprietaire.passwordRequestedAt`, `userProprietaire`.`roles` AS `userProprietaire.roles`, `userProprietaire`.`credentials_expired` AS `userProprietaire.credentialsExpired`, `userProprietaire`.`credentials_expire_at` AS `userProprietaire.credentialsExpireAt`, `userProprietaire`.`createdAt` AS `userProprietaire.createdAt`, `userProprietaire`.`dateNaissance` AS `userProprietaire.dateNaissance`, `userProprietaire`.`nom` AS `userProprietaire.nom`, `userProprietaire`.`mangoId` AS `userProprietaire.mangoId`, `userProprietaire`.`kycDocumentationId` AS `userProprietaire.kycDocumentationId`, `userProprietaire`.`walletLoueurId` AS `userProprietaire.walletLoueurId`, `userProprietaire`.`walletacheteurId` AS `userProprietaire.walletacheteurId`, `userProprietaire`.`lightysharecertifed` AS `userProprietaire.lightysharecertifed`, `userProprietaire`.`adressecertifed` AS `userProprietaire.adressecertifed`, `userProprietaire`.`telephonecertifed` AS `userProprietaire.telephonecertifed`, `userProprietaire`.`idcertifed` AS `userProprietaire.idcertifed`, `userProprietaire`.`updatedAt` AS `userProprietaire.updatedAt`, `userProprietaire`.`prenom` AS `userProprietaire.prenom`, `userProprietaire`.`mangoCardId` AS `userProprietaire.mangoCardId`, `userProprietaire`.`statut_user` AS `userProprietaire.statutUser`, `userProprietaire`.`answer_modal_statut` AS `userProprietaire.answerModalStatut`, `userProprietaire`.`quick_books_id` AS `userProprietaire.quickBooksId`, `userProprietaire`.`accepted_CGU_PC_NA_17_octobre_2018_At` AS `userProprietaire.acceptedCguPcNa17Octobre2018At`, `userProprietaire`.`accepted_CGU_17_octobre_2018` AS `userProprietaire.acceptedCgu17Octobre2018`, `userProprietaire`.`accepted_PC_17_octobre_2018` AS `userProprietaire.acceptedPc17Octobre2018`, `userProprietaire`.`accepted_NA_17_octobre_2018` AS `userProprietaire.acceptedNa17Octobre2018`, `userProprietaire`.`is_deleted` AS `userProprietaire.isDeleted`, `userProprietaire`.`kycDocumentationKbis` AS `userProprietaire.kycDocumentationKbis`, `userProprietaire`.`kycDocumentationStatut` AS `userProprietaire.kycDocumentationStatut`, `userProprietaire`.`kycDocumentationUbo` AS `userProprietaire.kycDocumentationUbo`, `userProprietaire`.`kycDocumentationSirene` AS `userProprietaire.kycDocumentationSirene`, `userProprietaire`.`is_expert` AS `userProprietaire.isExpert`, `userProprietaire`.`boutiqueActive` AS `userProprietaire.boutiqueActive`, `userProprietaire`.`dateChangementType` AS `userProprietaire.dateChangementType`, `userProprietaire`.`octobatPlazaId` AS `userProprietaire.octobatPlazaId`, `userProprietaire`.`octobatCustomerLightyId` AS `userProprietaire.octobatCustomerLightyId`, `userProprietaire`.`octobatCustomerFraisToUpdate` AS `userProprietaire.octobatCustomerFraisToUpdate`, `userProprietaire`.`verif_statut` AS `userProprietaire.verifStatut`, `userProprietaire`.`flag` AS `userProprietaire.flag`, `userProprietaire`.`mandat_id` AS `userProprietaire.mandatIdKey`, `userProprietaire`.`type_annulation_id` AS `userProprietaire.typeAnnulationIdKey`, `annonce`.`id` AS `annonce.id`, `annonce`.`titre` AS `annonce.titre`, `annonce`.`description` AS `annonce.description`, `annonce`.`valeurAchat` AS `annonce.valeurAchat`, `annonce`.`garantie` AS `annonce.garantie`, `annonce`.`createdAt` AS `annonce.createdAt`, `annonce`.`updatedAt` AS `annonce.updatedAt`, `annonce`.`publie` AS `annonce.publie`, `annonce`.`complete` AS `annonce.complete`, `annonce`.`AlaUne` AS `annonce.alaUne`, `annonce`.`quantity` AS `annonce.quantity`, `annonce`.`for_rent` AS `annonce.forRent`, `annonce`.`for_sale` AS `annonce.forSale`, `annonce`.`aLaUneProfile` AS `annonce.aLaUneProfile`, `annonce`.`etat` AS `annonce.etat`, `annonce`.`marque_id` AS `annonce.marqueIdKey`, `annonce`.`modele_id` AS `annonce.modeleIdKey`, `annonce`.`sous_categorie_id` AS `annonce.sousCategorieIdKey`, `annonce`.`user_id` AS `annonce.userIdKey`, `annonce`.`categorie_id` AS `annonce.categorieIdKey`, `typeAnnulation`.`id` AS `typeAnnulation.id`, `typeAnnulation`.`type` AS `typeAnnulation.type`, `userLocataire`.`id` AS `userLocataire.id`, `userLocataire`.`username` AS `userLocataire.username`, `userLocataire`.`username_canonical` AS `userLocataire.usernameCanonical`, `userLocataire`.`email` AS `userLocataire.email`, `userLocataire`.`email_canonical` AS `userLocataire.emailCanonical`, `userLocataire`.`enabled` AS `userLocataire.enabled`, `userLocataire`.`salt` AS `userLocataire.salt`, `userLocataire`.`password` AS `userLocataire.password`, `userLocataire`.`last_login` AS `userLocataire.lastLogin`, `userLocataire`.`locked` AS `userLocataire.locked`, `userLocataire`.`expired` AS `userLocataire.expired`, `userLocataire`.`expires_at` AS `userLocataire.expiresAt`, `userLocataire`.`confirmation_token` AS `userLocataire.confirmationToken`, `userLocataire`.`password_requested_at` AS `userLocataire.passwordRequestedAt`, `userLocataire`.`roles` AS `userLocataire.roles`, `userLocataire`.`credentials_expired` AS `userLocataire.credentialsExpired`, `userLocataire`.`credentials_expire_at` AS `userLocataire.credentialsExpireAt`, `userLocataire`.`createdAt` AS `userLocataire.createdAt`, `userLocataire`.`dateNaissance` AS `userLocataire.dateNaissance`, `userLocataire`.`nom` AS `userLocataire.nom`, `userLocataire`.`mangoId` AS `userLocataire.mangoId`, `userLocataire`.`kycDocumentationId` AS `userLocataire.kycDocumentationId`, `userLocataire`.`walletLoueurId` AS `userLocataire.walletLoueurId`, `userLocataire`.`walletacheteurId` AS `userLocataire.walletacheteurId`, `userLocataire`.`lightysharecertifed` AS `userLocataire.lightysharecertifed`, `userLocataire`.`adressecertifed` AS `userLocataire.adressecertifed`, `userLocataire`.`telephonecertifed` AS `userLocataire.telephonecertifed`, `userLocataire`.`idcertifed` AS `userLocataire.idcertifed`, `userLocataire`.`updatedAt` AS `userLocataire.updatedAt`, `userLocataire`.`prenom` AS `userLocataire.prenom`, `userLocataire`.`mangoCardId` AS `userLocataire.mangoCardId`, `userLocataire`.`statut_user` AS `userLocataire.statutUser`, `userLocataire`.`answer_modal_statut` AS `userLocataire.answerModalStatut`, `userLocataire`.`quick_books_id` AS `userLocataire.quickBooksId`, `userLocataire`.`accepted_CGU_PC_NA_17_octobre_2018_At` AS `userLocataire.acceptedCguPcNa17Octobre2018At`, `userLocataire`.`accepted_CGU_17_octobre_2018` AS `userLocataire.acceptedCgu17Octobre2018`, `userLocataire`.`accepted_PC_17_octobre_2018` AS `userLocataire.acceptedPc17Octobre2018`, `userLocataire`.`accepted_NA_17_octobre_2018` AS `userLocataire.acceptedNa17Octobre2018`, `userLocataire`.`is_deleted` AS `userLocataire.isDeleted`, `userLocataire`.`kycDocumentationKbis` AS `userLocataire.kycDocumentationKbis`, `userLocataire`.`kycDocumentationStatut` AS `userLocataire.kycDocumentationStatut`, `userLocataire`.`kycDocumentationUbo` AS `userLocataire.kycDocumentationUbo`, `userLocataire`.`kycDocumentationSirene` AS `userLocataire.kycDocumentationSirene`, `userLocataire`.`is_expert` AS `userLocataire.isExpert`, `userLocataire`.`boutiqueActive` AS `userLocataire.boutiqueActive`, `userLocataire`.`dateChangementType` AS `userLocataire.dateChangementType`, `userLocataire`.`octobatPlazaId` AS `userLocataire.octobatPlazaId`, `userLocataire`.`octobatCustomerLightyId` AS `userLocataire.octobatCustomerLightyId`, `userLocataire`.`octobatCustomerFraisToUpdate` AS `userLocataire.octobatCustomerFraisToUpdate`, `userLocataire`.`verif_statut` AS `userLocataire.verifStatut`, `userLocataire`.`flag` AS `userLocataire.flag`, `userLocataire`.`mandat_id` AS `userLocataire.mandatIdKey`, `userLocataire`.`type_annulation_id` AS `userLocataire.typeAnnulationIdKey`, `facture`.`id` AS `facture.id`, `facture`.`numero_facture_complet` AS `facture.numeroFactureComplet`, `facture`.`numero_facture` AS `facture.numeroFacture`, `facture`.`created_at` AS `facture.createdAt`, `facture`.`prix_ht` AS `facture.prixHt`, `facture`.`montant_tva` AS `facture.montantTva`, `facture`.`statut_user` AS `facture.statutUser`, `facture`.`factured_at` AS `facture.facturedAt`, `facture`.`lien_facture` AS `facture.lienFacture`, `demandeLocationLocationProblem`.`id` AS `demandeLocationLocationProblem.id`, `demandeLocationLocationProblem`.`createdAt` AS `demandeLocationLocationProblem.createdAt`, `demandeLocationLocationProblem`.`updatedAt` AS `demandeLocationLocationProblem.updatedAt`, `demandeLocationLocationProblem`.`type` AS `demandeLocationLocationProblem.type`, `demandeLocationLocationProblem`.`reason` AS `demandeLocationLocationProblem.reason`, `demandeLocationLocationProblem`.`message` AS `demandeLocationLocationProblem.message`, `demandeLocationLocationProblem`.`demandeLocation_id` AS `demandeLocationLocationProblem.demandeLocationIdKey`, `demandeLocationLocationProblem`.`user_id` AS `demandeLocationLocationProblem.userIdKey`, `demandeLocationLocationProblem`.`remboursement_id` AS `demandeLocationLocationProblem.remboursementIdKey`, `panierSession`.`id` AS `panierSession.id`, `panierSession`.`user_id` AS `panierSession.userId`, `panierSession`.`createdAt` AS `panierSession.createdAt`, `panierSession`.`dateDepart` AS `panierSession.dateDepart`, `panierSession`.`dateRetour` AS `panierSession.dateRetour`, `panierSession`.`nbr_jour_utilisation` AS `panierSession.nbrJourUtilisation`, `panierSession`.`prix_normal` AS `panierSession.prixNormal`, `panierSession`.`frais_service` AS `panierSession.fraisService`, `panierSession`.`prix_after_reduction` AS `panierSession.prixAfterReduction`, `panierSession`.`valeur_total_materiel` AS `panierSession.valeurTotalMateriel`, `panierSession`.`franchise` AS `panierSession.franchise`, `panierSession`.`caution` AS `panierSession.caution`, `panierSession`.`proprietaire_annonce_id` AS `panierSession.proprietaireAnnonceId`, `panierSession`.`numero` AS `panierSession.numero`, `panierSession`.`demande_location_id` AS `panierSession.demandeLocationId`, `panierSession`.`tab_annonces` AS `panierSession.tabAnnonces`, `panierSession`.`tab_bool_annonces` AS `panierSession.tabBoolAnnonces`, `panierSession`.`tauxTvaProprietaire` AS `panierSession.tauxTvaProprietaire`, `panierSession`.`tauxTvaFraisDeService` AS `panierSession.tauxTvaFraisDeService`, `panierSession`.`prix_location_ht` AS `panierSession.prixLocationHt`, `panierSession`.`prix_location_ttc` AS `panierSession.prixLocationTtc`, `panierSession`.`frais_service_ht` AS `panierSession.fraisServiceHt`, `panierSession`.`frais_service_ttc` AS `panierSession.fraisServiceTtc`, `panierSession`.`prix_total_ht` AS `panierSession.prixTotalHt`, `panierSession`.`prix_total_ttc` AS `panierSession.prixTotalTtc`, `panierSession`.`taxEvidenceId` AS `panierSession.taxEvidenceId`, `panierSession`.`taxEvidenceFraisDeServiceId` AS `panierSession.taxEvidenceFraisDeServiceId` FROM `demande_location` AS `demandeLocation` LEFT OUTER JOIN `facture_locataire` AS `factureLocataire` ON `demandeLocation`.`facture_locataire_id` = `factureLocataire`.`id` LEFT OUTER JOIN `fos_user` AS `userProprietaire` ON `demandeLocation`.`user_proprietaire_id` = `userProprietaire`.`id` LEFT OUTER JOIN `annonce` AS `annonce` ON `demandeLocation`.`annonce_id` = `annonce`.`id` LEFT OUTER JOIN `type_annulation` AS `typeAnnulation` ON `demandeLocation`.`type_annulation_id` = `typeAnnulation`.`id` LEFT OUTER JOIN `fos_user` AS `userLocataire` ON `demandeLocation`.`user_locataire_id` = `userLocataire`.`id` LEFT OUTER JOIN `facture` AS `facture` ON `demandeLocation`.`facture_id` = `facture`.`id` LEFT OUTER JOIN `location_problem` AS `demandeLocationLocationProblem` ON `demandeLocation`.`id` = `demandeLocationLocationProblem`.`demandeLocation_id` LEFT OUTER JOIN `panier_session` AS `panierSession` ON `demandeLocation`.`id` = `panierSession`.`demande_location_id` WHERE `demandeLocation`.`id` = '38578';
Executing (default): UPDATE `demande_location` SET `caution`=? WHERE `id` = ?
PUT /forest/demandeLocation/38578?timezone=Europe%2FAmsterdam 422 141 - 63.544 ms

Let’s fix the issue one by one here.

  1. Every backend change pushed to the production server doesn’t seems to appeared on Forest Admin interface (I’ve just added a new field)

I can see that both your development environment and production server are running with the same .forestadmin-schema.json, so I would say either:

  • The newly added field is hidden, and you should be able to set it visible in the UI
  • The field is not in the .forestadmin-schema.json. If that’s the case, the field was either not added to your model definition, or was added to your model definition but you didn’t restart your development server to regenerate the .forestadmin-schema.json

Let me know in which case you are, so we can go further on this issue.

  1. I don’t have any logs for the update error, only this one
    Executing (default): SELECT demandeLocation.id, demandeLocation

I see a few JOINs here, but nothing major.
As I can see in the thread @morganperre shared, 16382 is the default number of cached statement handle by the mysql2 package. What version of mysql2 are you using?

  1. I’ve got troubles to connect my development environment with an Unable to authenticate you error without any logs

Ok, so maybe we should start with this one first, that may allow you to test the SequelizeDatabaseError locally.
Unable to authenticate you means that one of the HTTP call used to authenticate you is failing. It should be visible in the developer console of your web browser (Network tabs), Could you share the response of this failing HTTP call?

Thanks in advance

2 Likes

This is all good, I’ve fixed this yesterday, sorry for the delay response.

Mysql is at version 5.7.16 , and I have no longer this issue by increasing max_prepared_stmt_count statements to the mysql config directly in the server. Thx for your time spending on this issue.

Last Issue to fix :slight_smile: :tada:

Capture d’écran 2022-01-14 à 15.59.25

The GET /forest/authentication is made directly by me in the browser through localhost:3310 but I don’t see logs from forestAdmin panel

@Timothy_Potter

I can see that this service is throwing a 404.

Could you also include your browser development console logs for further investigation.

I can’t be sure, but it looks like the OPTIONS/Preflight request is failing in your screenshot, which could indicate a CORS configuration issue.

Thx @jeffladiray , I’ll investigate this answer but it’s strange cors should be enabled for forestAdmin with this config :


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

if (process.env.CORS_ORIGINS) {
  allowedOrigins = allowedOrigins.concat(process.env.CORS_ORIGINS.split(','));
}

const corsConfig = {
  origin: allowedOrigins,
  maxAge: 86400, // NOTICE: 1 day
  credentials: true,
};

I’ll try to put directly in CORS_ORIGINS but which domaine name should I put ?
For the max_prepared_stmt_count statements,It spawn again with the new number limit which’s 30000 when we wan’t to edit datas from ForestAdmin back-office. The problem must be deeper do you have an idea if it can come from Mysql server configuration or more from my own forestAdmin code base ?

Thx in advance

You can refer to this part of our documentation in order to check if your CORS configuration is up-to-date.

Could you also please share your browser development console logs for further investigation?

For the max_stmt issue, having the version of the mysql2 package you are using would help.

Thanks in advance :pray:

Hi @jeffladiray

Everythings seems to be set as it said in your documentation link


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

if (process.env.CORS_ORIGINS) {
  allowedOrigins = allowedOrigins.concat(process.env.CORS_ORIGINS.split(','));
}

const corsConfig = {
  origin: allowedOrigins,
  maxAge: 86400, // NOTICE: 1 day
  credentials: true,
};

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('null')
}));
app.use(cors(corsConfig));


Hope this can help :slight_smile:

"mysql2": "~2.2.5",

Thx for all !

I was talking of the developer console errors you encounter while having the “Unable to authenticate you” message.
This one will be especially useful to fix this issue.