/rest/webResources/1.0/resources fails with NullPointerException. Client side extensions don't load

Dear Community!
We have implemented client side extensions “Extension point: bitbucket.ui.pullrequest.overview.summary” for our flow. We have changed it from button to modal recently. However it is often not displayed. If I refresh the screen several times then “sometimes” it works… But it looks like I don’t really have influence on it.

After debugging the calls it turned out that there is POST call to
https://<bitbucket_host>/rest/webResources/1.0/resources which fails(often) with error code 500 NullPointerException. Unfortunately this seems to be an undocumented API so we can not fix it by ourselves.

(BAD) REQUEST

{
    "r": [],
    "c": [
        "bitbucket.ui.pullrequest.overview.summary"
    ],
    "xc": [
        "_super",
        "bitbucket.page.pullRequest.detail",
        "bitbucket.layout.repository",
        "atl.general",
        "bitbucket.layout.base",
        "bitbucket.layout.entity",
        "bitbucket.ui.pullrequest.action"
    ],
    "xr": []
}

RESPONSE 500

?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<status>
    <status-code>500</status-code>
    <stack-trace>java.lang.NullPointerException
</stack-trace>
</status>

also in logs we only see null

2021-06-29 00:08:57,814 ERROR [http-nio-7990-exec-369] dmitry.tsybin @KEJ5UOx8x8415083x1 xe0nh0 46.146.243.241,127.0.0.1 "POST /rest/webResources/1.0/resources HTTP/1.0" c.a.p.r.c.e.j.ThrowableExceptionMapper Uncaught exception thrown by REST service: null
java.lang.NullPointerException: null
2021-06-29 00:09:09,379 ERROR [http-nio-7990-exec-380] dmitry.tsybin @KEJ5UOx9x8415149x0 xe0nh0 46.146.243.241,127.0.0.1 "POST /rest/webResources/1.0/resources HTTP/1.0" c.a.p.r.c.e.j.ThrowableExceptionMapper Uncaught exception thrown by REST service: null
java.lang.NullPointerException: null
2021-06-29 00:14:11,988 ERROR [http-nio-7990-exec-383] thomas @KEJ5UOx14x8415569x0 3jstoj 178.62.243.91,127.0.0.1 "POST /rest/webResources/1.0/resources HTTP/1.0" c.a.p.r.c.e.j.ThrowableExceptionMapper Uncaught exception thrown by REST service: null
java.lang.NullPointerException: null
2021-06-29 00:23:30,351 ERROR [http-nio-7990-exec-385] ashkan @KEJ5UOx23x8416226x0 y3alqd 46.146.243.241,127.0.0.1 "POST /rest/webResources/1.0/reso

However when it works then
GOOD REQUEST

{
    "r": [],
    "c": [
        "bitbucket.ui.pullrequest.overview.summary",
        "bitbucket.ui.pullrequest.comment.action"
    ],
    "xc": [
        "_super",
        "bitbucket.page.pullRequest.detail",
        "bitbucket.layout.repository",
        "atl.general",
        "bitbucket.layout.base",
        "bitbucket.layout.entity",
        "bitbucket.ui.pullrequest.action"
    ],
    "xr": []
}

RESPONSE 200

{
    "resources": [
        {
            "url": "/s/b77adcca98bde9a6262f6d800a04d5b6-CDN/-1209951088/acd5b22/216/29a2e9b196a1c8c795c4c0fb4fa812d4/_/download/contextbatch/css/bitbucket.ui.pullrequest.overview.summary,bitbucket.ui.pullrequest.comment.action,-_super,-bitbucket.page.pullRequest.detail,-atl.general,-bitbucket.layout.repository,-bitbucket.ui.pullrequest.action,-bitbucket.layout.base/batch.css?isJiraLinked=true&slack-enabled=true",
            "resourceType": "CSS",
            "ieOnly": false,
            "key": "bitbucket.ui.pullrequest.overview.summary,bitbucket.ui.pullrequest.comment.action,-_super,-bitbucket.page.pullRequest.detail,-atl.general,-bitbucket.layout.repository,-bitbucket.ui.pullrequest.action,-bitbucket.layout.base",
            "batchType": "context"
        },
...

The difference is “c”, however I cannot influence what is passed there. I can only refresh screen several times

Here is the client side extension code that we use:

/**
 * @clientside-extension
 * @extension-point bitbucket.ui.pullrequest.overview.summary
 */
export default ModalExtension.factory((extensionAPI, context) => {
     getData({ context, type: ExtensionElement.BUTTON }).then(({ hidden, e2eStatus }) => {
         let customOnAction = (modalAPI) => {};
         if (e2eStatus.state === AutotestsState.NOT_COMPLETED || e2eStatus.state === AutotestsState.UNKNOWN) {
             console.log("opened modal extension to add job with parameters")
             customOnAction = (modalAPI) => {
                 const getContent = prepare_table;

                 modalAPI.setTitle('Set parameters for E2E');

                 modalAPI.onMount(container => {
                     container.innerHTML = getContent();
                 });

                 modalAPI.onUnmount(container => {
                     container.innerHTML = '';
                 });

                 modalAPI.setActions([
                     {
                         text: 'Submit',
                         onClick: async () => {
                             const java_e2e_branch = document.getElementById("test_branch").value;
                             const run_all_tests = document.getElementById("run_all_tests").value;
                             const browser_version = document.getElementById("browser_version").value;
                             const mobile_branch = document.getElementById("mobile_branch").value;
                             const repositoryName = context.repository.name.toLowerCase()
                             await runE2eTests(e2eStatus, extensionAPI,run_all_tests,java_e2e_branch,browser_version,mobile_branch,repositoryName);

                             modalAPI.closeModal();
                         }
                     },
                     {
                         text: 'Close',
                         onClick: () => {
                             modalAPI.closeModal()
                         },
                     },

                 ]);
             }
         }
         
         extensionAPI.updateAttributes({
             iconBefore: 'jira/labs',
             hidden,
             label: 'Configure and Add to E2E test queue',
             onAction: customOnAction
         })
     })

     return {
         iconBefore: 'jira/labs',
         hidden: true,
         label: 'Configure and Add to E2E test queue',
         onAction: modalAPI => {}
     }
})

I have tried to reproduce on Docker Bitbucket server 7.8.0 but the issue does not occur. But it does on our prod server and it’s not good that we need to refresh so many times.
I was directed from Client side extensions atlassian / atlassian-clientside-extensions / issues / #13 - Client Side extensions are not displayed when call to /rest/webResources/1.0/resources fails — Bitbucket to bitbucket support SSP-49524 an from there to here…

I have created a loom video with the issue live Loom | Free Screen & Video Recording Software
Can you help us solve it?

Hi @BalazsGalambos, can you please answer the support ticket you have created?

yes. We are collecting the logs right now. We just need to align with other teams. We going to send logs today. BTW I have some updates. During the weekend we experimented a bit and found that if we have a button type extension between the extensions then the problem does not appear. So we added a button which is always hidden.

done. I attached logs in support ticket.

1 Like

Hey @madamczak . I see the fix is ready for below task, however I don’t know where these versions 5.4.2, 4.4.0 integrate to… I mean do I need to update bitbucket server to a given version eg7.16 or do I need to update only one module of the server somehow?

https://ecosystem.atlassian.net/browse/PLUGWEB-612

Hi @BalazsGalambos, you can’t change the version of WRM, it’s bundled into the product.

The best solution I can recommend is to find what version of WRM is used by Bitbucket is to check this page: atlassian / platform-module-usage / wiki / atlassian-plugins-webresource — Bitbucket

So far, Bitbucket is using WRM in version 4.2.9 and it will be updated to version 4.4.0 soon.