Description
On a Divi 5 page that uses a third-party module (Divi Flash's difl/*, and I would expect any third-party namespace such as decm/* or d5bgo/*), page_get_layout reports the module and hands back a targeting identifier that carries its namespace, for example difl/faq:1. Every write and targeting path then rejects that same identifier, because those paths assume the divi/ namespace. The result is a read/write asymmetry: the plugin gives you a target it will not accept back.
In practice the page can be inspected through the API but its third-party modules cannot be edited through it. The only workaround is to rebuild the raw block comment by hand outside the plugin, which gets fragile fast once a page has more than a couple of modules.
Environment
- WordPress: 7.0.2
- Divi: 5.9.0
- diviops-agent plugin: 1.5.10
- PHP: 8.5.8
The bug is in the plugin's REST layer, so it reproduces independently of the @diviops/mcp-server version, and it surfaces the same way through the MCP tools that call these routes.
Steps to reproduce
- On a Divi 5 page, add any third-party module, for example Divi Flash's FAQ (
difl/faq) or Counter (difl/counter).
- Read the page with
page_get_layout (GET /diviops/v1/page/get-layout/<id>). The third-party module is reported with an auto_index that keeps its namespace, e.g. difl/faq:1.
- Pass that exact identifier to
module_get, module_update, or module_move (or the corresponding MCP tools).
- Do the same with a Theme Builder insert whose content is a third-party module.
Expected
The identifier that page_get_layout returns resolves in every operation, the same way a divi/* identifier does.
Actual
module_get / module_update / module_move fail to resolve difl/faq:1, and parse_divi_blocks_for_insert() returns a 400 for a non-divi/ top-level block. schema_get_module also 404s for difl/faq, because the name gets a divi/ prefix and becomes divi/difl/faq.
Root cause
The read path is namespace-agnostic but the write and targeting paths are not. The raw block-comment scanners behind module_update, find_block (used by module_get and module_move), and the section scanners find the end of a block name by scanning to the first space or slash after <!-- wp:, which truncates a namespaced name (difl/faq becomes difl, since the name contains a slash). page_get_layout derives its identifier with a plain str_replace('divi/', '', $name), which leaves a third-party name intact, so the two halves disagree. Theme Builder insert and parse_tb_parent_selector() additionally require the literal divi/ prefix, and schema_get_module prepends it unconditionally.
A couple of related points that matter for a complete fix: the write-safety marker counting and the block-attribute normalization also key off divi/, so a namespace-agnostic fix has to widen those too without letting them touch unrelated Gutenberg blocks. Scoping normalization to Divi modules is not as simple as a registry lookup, because Divi's own core modules (divi/text, divi/section) are largely not present in WP_Block_Type_Registry, while third-party modules are. Namespace has to be trusted first, with the module/child-module block category as the fallback signal for third-party modules.
Offer
I have a fix that makes targeting namespace-agnostic end to end: a single identifier mapping used by both the read and the write paths, scanners that match the actual block-name grammar so a namespaced name is not truncated, the self-closing and depth-pairing scans made namespace-aware, and normalization scoped to Divi modules by namespace or block category. It is verified against a live page carrying difl/* and d5bgo/* modules alongside native Divi ones, with the native divi/* behavior unchanged. Happy to share the patch or walk through the reasoning in whatever form is easiest for your upstream workflow.
Description
On a Divi 5 page that uses a third-party module (Divi Flash's
difl/*, and I would expect any third-party namespace such asdecm/*ord5bgo/*),page_get_layoutreports the module and hands back a targeting identifier that carries its namespace, for exampledifl/faq:1. Every write and targeting path then rejects that same identifier, because those paths assume thedivi/namespace. The result is a read/write asymmetry: the plugin gives you a target it will not accept back.In practice the page can be inspected through the API but its third-party modules cannot be edited through it. The only workaround is to rebuild the raw block comment by hand outside the plugin, which gets fragile fast once a page has more than a couple of modules.
Environment
The bug is in the plugin's REST layer, so it reproduces independently of the
@diviops/mcp-serverversion, and it surfaces the same way through the MCP tools that call these routes.Steps to reproduce
difl/faq) or Counter (difl/counter).page_get_layout(GET /diviops/v1/page/get-layout/<id>). The third-party module is reported with anauto_indexthat keeps its namespace, e.g.difl/faq:1.module_get,module_update, ormodule_move(or the corresponding MCP tools).Expected
The identifier that
page_get_layoutreturns resolves in every operation, the same way adivi/*identifier does.Actual
module_get/module_update/module_movefail to resolvedifl/faq:1, andparse_divi_blocks_for_insert()returns a 400 for a non-divi/top-level block.schema_get_modulealso 404s fordifl/faq, because the name gets adivi/prefix and becomesdivi/difl/faq.Root cause
The read path is namespace-agnostic but the write and targeting paths are not. The raw block-comment scanners behind
module_update,find_block(used bymodule_getandmodule_move), and the section scanners find the end of a block name by scanning to the first space or slash after<!-- wp:, which truncates a namespaced name (difl/faqbecomesdifl, since the name contains a slash).page_get_layoutderives its identifier with a plainstr_replace('divi/', '', $name), which leaves a third-party name intact, so the two halves disagree. Theme Builder insert andparse_tb_parent_selector()additionally require the literaldivi/prefix, andschema_get_moduleprepends it unconditionally.A couple of related points that matter for a complete fix: the write-safety marker counting and the block-attribute normalization also key off
divi/, so a namespace-agnostic fix has to widen those too without letting them touch unrelated Gutenberg blocks. Scoping normalization to Divi modules is not as simple as a registry lookup, because Divi's own core modules (divi/text,divi/section) are largely not present inWP_Block_Type_Registry, while third-party modules are. Namespace has to be trusted first, with themodule/child-moduleblock category as the fallback signal for third-party modules.Offer
I have a fix that makes targeting namespace-agnostic end to end: a single identifier mapping used by both the read and the write paths, scanners that match the actual block-name grammar so a namespaced name is not truncated, the self-closing and depth-pairing scans made namespace-aware, and normalization scoped to Divi modules by namespace or block category. It is verified against a live page carrying
difl/*andd5bgo/*modules alongside native Divi ones, with the nativedivi/*behavior unchanged. Happy to share the patch or walk through the reasoning in whatever form is easiest for your upstream workflow.