I'm getting the following error and stack trace when submitting a form on a CraftCMS-3.7 website...

HTTP 404 – Not Found – yii\web\NotFoundHttpException
Page not found.
Caused by: Invalid Route – yii\base\InvalidRouteException
Unable to resolve the request "contactForm/sendMessage".
1. in [redacted]/vendor/craftcms/cms/src/web/Application.phpat line 600
591592593594595596597598599600601602603604605606607608609            $route = implode('/', $request->getActionSegments());

        try {
            Craft::debug("Route requested: '$route'", __METHOD__);
            $this->requestedRoute = $route;
            return $this->runAction($route, $_GET);
        } catch (\Throwable $e) {
            if ($e instanceof InvalidRouteException) {
                throw new NotFoundHttpException(Craft::t('yii', 'Page not found.'), $e->getCode(), $e);
            throw $e;

    return null;

2. in [redacted]/vendor/craftcms/cms/src/web/Application.php at line 266– craft\web\Application::_processActionRequest(craft\web\Request)
260261262263264265266267268269270271272                    throw new ForbiddenHttpException();

    // If this is an action request, call the controller
    if (($response = $this->_processActionRequest($request)) !== null) {
        return $response;

    // If we're still here, finally let Yii do it's thing.
    try {
        return parent::handleRequest($request);
3. in [redacted]/vendor/yiisoft/yii2/base/Application.php at line 384– craft\web\Application::handleRequest(craft\web\Request)
4. in [redacted]/web/index.php at line 12– yii\base\Application::run()
6789101112// Load shared bootstrap
require '../bootstrap.php';

// Load and run Craft
/** @var craft\web\Application $app */
$app = require CRAFT_VENDOR_PATH . '/craftcms/cms/bootstrap/web.php';

And the HTML for the form...

<form id="contact-form" method="post" action="" accept-charset="UTF-8">
        <h3>Schedule a Demo?</h3>

        <input id="vona" name="vona" type="text" style="display:none;">
        <input type="hidden" name="action" value="contactForm/sendMessage">
        <input type="hidden" name="redirect" value="/thank-you">

        <label for="name">Name</label>
        <input id="name" placeholder="Name" class="required" type="text" name="Name" value="">

        <label for="title">Company / Job Title</label>
        <input id="title" name="Company" placeholder="Company" class="required" type="text">

        <label for="email">Email Address</label>
        <input id="email" placeholder="Email Address" class="required" type="text" name="Email" value="">
        <input id="hidden-email" name="Email" type="text" style="display:none;" autocomplete="off" />

        <textarea id="message" class="required" name="Message" placeholder="Message" id="" cols="30" rows="10"></textarea>
        <input type="submit" value="Submit" id="formSubmitBtn" />

I thought that maybe I had the wrong value for the action input, but the same 'Unable to resolve the request "contactForm/sendMessage"' error message is returned regardless of what is listed as its value.

  • It might be helpful to know that this site was migrated from 2.x to 3.x then moved to a different host at one point. The original live site doesn't have this same problem, but I can't find any errors or warnings that would indicate a problem with the migrated site.
    – soupmagnet
    Commented Jan 26, 2022 at 18:12

1 Answer 1


Your suspicion about the Craft 2 -> 3 migration is dead-on.

Yii changed how action attributes work between versions 1 and 2 (used in Craft 2 and 3, respectively), so you'll need to update contactForm/sendMessage to contact-form/send-message!

A couple more notes for your Craft 3 journey:

  • There are some handy Twig helpers now to simplify these hidden inputs:
    • {{ actionInput('my-controller/action-name') }} (Docs)
    • {{ redirectInput('some-path') }} (Docs)
    • {{ hiddenInput('fieldName', myValue) }} (Docs)
  • CSRF protection should probably be enabled to reduce malicious/spam submissions.

Here's the relevant upgrade documentation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.