FreshRSS/FreshRSS · error · Minz_ActionException

Invalid action name “{action_name}” for controller “{control

Error message

Invalid action name “{action_name}” for controller “{controller_name}”.

What it means

Minz_Dispatcher::launchAction() builds the callable [$this->controller, $action_name] and requires is_callable(); in practice the controller must expose a public instance method <action>Action(). Otherwise Minz_ActionException is thrown, carrying the controller class name and the raw action name from the URL.

Source

Thrown at lib/Minz/Dispatcher.php:115

		if (!($controller instanceof Minz_ActionController)) {
			throw new Minz_ControllerNotActionControllerException(
				$controller_name,
				Minz_Exception::ERROR
			);
		}

		$this->controller = $controller;
	}

	/**
	 * Launch the action on the dispatcher’s controller
	 * @param string $action_name the name of the action
	 * @throws Minz_ActionException if the action cannot be executed on the controller
	 */
	private function launchAction(string $action_name): void {
		$call = [$this->controller, $action_name];
		if (!is_callable($call)) {
			throw new Minz_ActionException(
				get_class($this->controller),
				$action_name,
				Minz_Exception::ERROR
			);
		}
		if (Minz_ExtensionManager::callHook(Minz_HookType::ActionExecute, $this->controller) !== false) {
			call_user_func($call);
		}
	}

	/**
	 * Register a controller file.
	 *
	 * @param string $base_name the base name of the controller (i.e. ./?c=<base_name>)
	 * @param string $base_path the base path where we should look into to find info.
	 */
	public static function registerController(string $base_name, string $base_path): void {
		if (!self::isRegistered($base_name)) {

View on GitHub (pinned to 95842d81c1)

Solutions

  1. Check the 'a' value and confirm a public method <action>Action() exists on the controller class named in the message
  2. If FreshRSS renamed the action, update the URL, bookmark, or client to the new name
  3. For custom actions, implement public function <action>Action(): void on the controller
  4. When generating links dynamically, build them from the controller's actual action names

Example fix

// before: link still uses the old action name after a rename
echo Minz_Url::display(['c' => 'feed', 'a' => 'oldName']);

// after: rename kept consistent with the controller method
// controller: public function newNameAction(): void { ... }
echo Minz_Url::display(['c' => 'feed', 'a' => 'newName']);
Defensive patterns

Strategy: validation

Validate before calling

$action = 'update';
$method = $action . 'Action';
if (!is_callable([$controller, $method])) {
	// the URL requests an action this controller does not expose: use the default action
	$action = 'index';
}

Type guard

function actionIsCallable(object $controller, string $action): bool {
	return is_callable([$controller, $action . 'Action']);
}

Try / catch

try {
	// dispatch the request
} catch (Minz_ActionException $e) {
	// controller/action pair from the URL does not exist: render 404
	Minz_Error::error(404, ['error_message' => 'Unknown action ' . $e->getMessage()]);
}

Prevention

When it happens

Trigger: ?c=<controller>&a=<action> where method <action>Action() does not exist or is not public (private/protected, or static); an action renamed in a FreshRSS upgrade while old links or clients still request the previous name; an extension route pointing at a method that was never implemented.

Common situations: Bookmarked URLs after an upgrade renamed actions; third-party mobile clients calling removed endpoints; typos in hand-written URLs; extension development against a changed controller.

Related errors


AI-assisted analysis of FreshRSS/FreshRSS@95842d81c1 (2026-08-23). Data as JSON: /api/errors/6bf03ece95a3b90c. Report an issue: GitHub.