Skip to content

wp_register_ability returns NULL when called from plugin during wp_abilities_api_init #135

@gelakhubutia

Description

@gelakhubutia

Description

When trying to register a custom ability from a WordPress plugin using the recommended wp_abilities_api_init hook, wp_register_ability consistently returns NULL even when called correctly during the action.

Environment

  • WordPress 6.9.1 (Abilities API built into core)
  • MCP Adapter plugin v0.4.1 (installed via Composer with Jetpack autoloader)
  • WooCommerce 10.5.2
  • PHP 8.x, shared hosting (cPanel)

Steps to Reproduce

  1. Install wordpress/mcp-adapter via Composer in wp-content/plugins/
  2. Create a plugin with the following code:
add_action( 'wp_abilities_api_init', function() {
    $result = wp_register_ability( 'my-plugin/my-ability', [
        'label'       => 'My Ability',
        'description' => 'Test ability',
        'input_schema' => [ 'type' => 'object', 'properties' => [] ],
        'execute_callback' => function( $input ) { return [ 'success' => true ]; },
        'permission_callback' => function() { return current_user_can( 'manage_options' ); },
        'meta' => [ 'show_in_rest' => true ],
    ]);
    error_log( 'Result: ' . ( $result ? get_class( $result ) : 'NULL' ) );
}, 5 );

add_action( 'plugins_loaded', function() {
    if ( class_exists( 'WP\MCP\Core\McpAdapter' ) ) {
        \WP\MCP\Core\McpAdapter::instance();
    }
}, 1 );
  1. Run wp eval 'var_dump(array_keys(wp_get_abilities()));'

Expected Behavior

my-plugin/my-ability should appear in the abilities list.

Actual Behavior

wp_register_ability returns NULL. The hook fires correctly (doing_action('wp_abilities_api_init') returns true), but the registration silently fails.

Debug Findings

  • doing_action('wp_abilities_api_init') returns YES inside the callback ✅
  • wp_register_ability is loaded from wp-includes/abilities-api.php (core) ✅
  • McpAdapter::instance() successfully initializes ✅
  • WooCommerce is also hooked into wp_abilities_api_init and its abilities register fine
  • The registry appears to already be initialized before our plugin's callback runs, possibly due to WooCommerce triggering WP_Abilities_Registry::get_instance() first

Question

Is there a timing conflict between WooCommerce's bundled abilities-api vendor copy and WordPress core's native implementation in 6.9? Is there a recommended way to register abilities from a plugin when WooCommerce is also present?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions