Skip to content

LinkControl crashing block in Pattern Editor #65874

Closed

Description

@StYankov

Description

The LinkControl component from the @wordpress/block-editor package does not work as expected when used inside the Pattern Editor. The block crashes with some JS errors in the console:
Image

Here's the error with SCRIPT_DEBUG set to true
Image

Step-by-step reproduction instructions

Steps to Reproduce

  1. Create a Pattern with a block that contains a LinkControl Image

  2. Open Pattern Editor

  3. Open the Pattern with the LinkControlImage

All I know is that the error is caused by the useCopyToClipboard hook inside used by LinkPreview component internally in LinkControl.
I tried installing the Gutenberg Plugin 19.3 but it still crashes.

Screenshots, screen recording, code snippet

I created a simple test repo with WP and a theme with block that contains a LinkControl to reproduce the issue: repo block edit.js

Environment info

WordPress Version: 6.6.2
Browser: Chrome 127

Please confirm that you have searched existing issues in the repo.

  • Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

  • Yes

UPDATE:
The issue appears after WP 6.5. Before that the example block doesn't crash in the Pattern Editor.
Update:
Added a comment describing the problem and a possible solution

Activity

  1. added
    [Type] BugAn existing feature does not function as intended
    on Oct 4, 2024
  2. added
    Needs TestingNeeds further testing to be confirmed.
    [Feature] Link EditingLink components (LinkControl, URLInput) and integrations (RichText link formatting)
    on Oct 4, 2024
  3. github-actions commented on Nov 4, 2024

    @github-actions

    Hi,
    This issue has gone 30 days without any activity. This means it is time for a check-in to make sure it is still relevant. If you are still experiencing this issue with the latest versions, you can help the project by responding to confirm the problem and by providing any updated reproduction steps.
    Thanks for helping out.

  4. added
    [Status] StaleGives the original author opportunity to update before closing. Can be reopened as needed.
    on Nov 4, 2024
  5. StYankov commented on Nov 4, 2024

    @StYankov
    Author

    Hello.
    I have some progress with the investigation of the issue. Here's what I found.
    In Gutenberg v17.6 a new feature was added to the component through this commit (PR #58170) . Here a new "Copy to Clipboard" button is added in the LinkPreview component used internally in the LinkControl. The feature itself works great in the normal editor for pages/posts and so on.

    The issue happens only in the Patterns Editor and here's why:
    The copy to clipboard functionality is performed through the useCopyToClipboard hook from @wordpress/compose
    The useCopyToClipboard hook uses clipboard.js npm library (code reference).
    clipboard.js uses the good-listener npm library to attach the click event to the button (code reference).

    Before good-listener attached the event to the node it does some checks to ensure that the passed target is valid.
    Here's where it get's wrong: This check is.node(target) always returns false.

    Here's how the is.node expanded:

    exports.node = function(value) {
        return value !== undefined
            && value instanceof HTMLElement
            && value.nodeType === 1;
    };
    

    At first sight it shouldn't return false because:
    a) value is not undefined. It's a <button>
    b) HTMLButtonElement is an instance of HTMLElement
    c) value.nodeType === 1

    However, the pattern editor is rendered inside an iframe. Thus the check value instanceof HTMLElement checks if the value is instance of iframe's parent window.HTMLElement instead of the iframe's window.HTMLElement which will always be false.
    Image

    After the target validity check is made and the target is deemed invalid the clipboard.js throws an Error and breaks the component.

    Possible fixes
    I don't think we have any chance of changing the good-listener npm library to add support for iframes. The last update has been 7 years ago and it seems to be abandoned/not maintained anymore.
    Another approach would be to enable this "Copy to clipboard" feature only in the block editor. It will not be rendered in the patterns editor and the error should be fixed.

  6. removed
    [Status] StaleGives the original author opportunity to update before closing. Can be reopened as needed.
    on Nov 4, 2024
  7. Mamaduka commented on Nov 4, 2024

    @Mamaduka
    Member
  8. getdave commented on Nov 4, 2024

    @getdave
    Contributor

    Thanks for reporting this.

    I wasn't able to replicate. I created a Pattern containing a Button block but saw no error when trying to edit the original of the Pattern.

    Is there anything else I missed here?

  9. StYankov commented on Nov 4, 2024

    @StYankov
    Author

    @getdave
    Hello and thank you for your time.
    You are right that when you create a paragraph with a link for example it works in the pattern editor.
    With further testing I discovered that the inline links in Paragraphs or Buttons are places inside a Popover component.
    What this does it it moves the LinkControl component outside the iframe. This way the is.node check passes because the HTMLElement is from the right context (The host page).
    Image

    So maybe the solution would be to always wrap the LinkControl inside a Popover if we want it to work inside the Pattern Editor ?

    Here's an example where it breaks EXAMPLE (It's a custom component)

  10. getdave commented on Nov 5, 2024

    @getdave
    Contributor

    @StYankov Thanks for narrowing down the cause. LinkControl should ideally be useable within the iframe. So this is a bug but as you say one that is very difficult to fix due to the dependency graph.

  11. getdave commented on Nov 5, 2024

    @getdave
    Contributor

    Looks like there are a lot of usages of copyToClipboard() see here which means this bug might also manifest for those situations.

  12. github-actions commented on Dec 6, 2024

    @github-actions

    Hi,
    This issue has gone 30 days without any activity. This means it is time for a check-in to make sure it is still relevant. If you are still experiencing this issue with the latest versions, you can help the project by responding to confirm the problem and by providing any updated reproduction steps.
    Thanks for helping out.

  13. added
    [Status] StaleGives the original author opportunity to update before closing. Can be reopened as needed.
    on Dec 6, 2024
  14. removed
    [Status] StaleGives the original author opportunity to update before closing. Can be reopened as needed.
    on Apr 30, 2025
  15. github-actions commented on May 31, 2025

    @github-actions

    Hi,
    This issue has gone 30 days without any activity. This means it is time for a check-in to make sure it is still relevant. If you are still experiencing this issue with the latest versions, you can help the project by responding to confirm the problem and by providing any updated reproduction steps.
    Thanks for helping out.

  16. added
    [Status] StaleGives the original author opportunity to update before closing. Can be reopened as needed.
    on May 31, 2025
  17. removed
    [Status] StaleGives the original author opportunity to update before closing. Can be reopened as needed.
    on Jun 12, 2025
  18. t-hamano commented on Jul 5, 2025

    @t-hamano
    Contributor

    Looks like there are a lot of usages of copyToClipboard() see here which means this bug might also manifest for those situations.

    I think this is true. It can happen for any component that has a useCopyToClipboard hook.

    For example, if the editor is an iframe, and a ClipboardButton component is used inside a block:

    import { useBlockProps } from '@wordpress/block-editor';
    import { ClipboardButton } from '@wordpress/components';
    
    export default function CodeEdit() {
    	const blockProps = useBlockProps();
    	return (
    		<div { ...blockProps }>
    			<ClipboardButton variant="primary" text="Text to be copied.">
    				Copy Text
    			</ClipboardButton>
    		</div>
    	);
    }

    If the problem can be resolved with a minor modification to the good-listener library itself, it might be possible to consider applying a patch.

    https://github.com/WordPress/gutenberg/blob/trunk/patches/README.md

  19. mostafa-abdelbari commented on Feb 17, 2026

    @mostafa-abdelbari

    The issue still exists. For my case, when using LinkControl directly within the edit function of a block using apiVersion: 3, the editor crashes as soon as a URL is selected. This is due to the clipboard utility in @wordpress/compose failing to find the target element within the isolated iframe context.

    Steps to Reproduce:

    1. Create a block with "apiVersion": 3 in block.json.
    2. Implement LinkControl within the main edit.js (Canvas area), not the InspectorControls.
    3. Select a block, enter a URL, and select a suggestion.
    4. Result: The editor crashes with: Uncaught TypeError: First argument must be a String, HTMLElement, HTMLCollection, or NodeList at listen (compose.js).
  20. t-hamano commented on Feb 17, 2026

    @t-hamano
    Contributor

    Possible fixes
    I don't think we have any chance of changing the good-listener npm library to add support for iframes. The last update has been 7 years ago and it seems to be abandoned/not maintained anymore.
    Another approach would be to enable this "Copy to clipboard" feature only in the block editor. It will not be rendered in the patterns editor and the error should be fixed.

    We should be able to solve this by patching this library in the Gutenberg project.

  21. mostafa-abdelbari commented on Feb 17, 2026

    @mostafa-abdelbari

    Thanks for the update. Since patching the library internally is the plan, is there anything I need to do on my side, or should I just wait for the core fix?

    Also, since this makes LinkControl unusable in the iframe contexts, are there any recommended workarounds to bypass this issue?

  22. t-hamano commented on Feb 19, 2026

    @t-hamano
    Contributor

    I did a bit of research and found that the root cause isn't just good-listener. There are also issues with the Clipboard library itself.

    For example, here it is referencing the root document and using the deprecated execCommand method.

    https://github.com/zenorocha/clipboard.js/blob/899378dee9681dcf4cb3d702c23a3f3cd9f473d8/src/common/command.js#L8

    Unfortunately, clipboard.js hasn't been updated in several years and the iframe issue is unlikely to be resolved.

    zenorocha/clipboard.js#470

    Perhaps the issue can be resolved by applying a patch via patch-package, but it may be time to move on from the dependency on Clipboard.js.

    We may be able to implement native code or replace it with a different library. I think this issue should be addressed before the post editor is fully moved to iframes. cc @ellatrix

    Also, since this makes LinkControl unusable in the iframe contexts, are there any recommended workarounds to bypass this issue?

    @mostafa-abdelbari Currently the only solution would be to use a LinkControl outside of the iframe, such as a block sidebar or popover.

  23. t-hamano commented on Feb 19, 2026

    @t-hamano
    Contributor

    I have refactored the hook that is causing the problem by using the native API. #75723

  24. aaronjorbin commented on May 19, 2026

    @aaronjorbin
    Member

    @mostafa-abdelbari Thank you for helping on this! Would you be able to link your WordPress and Github accounts to ensure your work is properly credited in WordPress releases?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

[Feature] Link EditingLink components (LinkControl, URLInput) and integrations (RichText link formatting)[Status] In ProgressTracking issues with work in progress[Type] BugAn existing feature does not function as intended

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions