cli-microsoft365 icon indicating copy to clipboard operation
cli-microsoft365 copied to clipboard

Bug report: `entra m365group remove` does not work

Open Adam-it opened this issue 1 month ago • 4 comments

Priority

(Urgent) I can't use the CLI

Description

When we added a fix to this #6618 by adding https://github.com/pnp/cli-microsoft365/blob/b2b02aef3617e6d5d159a5cb870bf0b7d55d713e/src/request.ts#L234-L237

We introduced a new bug in entra m365group remove command. In this command, when we remove the associated SharePoint site with the entra group, we first retrieve its full URL https://github.com/pnp/cli-microsoft365/blob/b2b02aef3617e6d5d159a5cb870bf0b7d55d713e/src/m365/entra/commands/m365group/m365group-remove.ts#L111 and then pass it over to deleteM365GroupSite method in which the site full URL is passed as a query option in the request URL https://github.com/pnp/cli-microsoft365/blob/b2b02aef3617e6d5d159a5cb870bf0b7d55d713e/src/m365/entra/commands/m365group/m365group-remove.ts#L165-L171

What will happen is when we retrieve and pass a SharePoint site with URL: https://aaa.bbb/ccc in the request.post processing, we will end up with URL https:/aaa.bbb/ccc as the trailing / gets removed.

Screenshot from running the entra m365group remove with debug option

Image

Steps to reproduce

simply run entra m365group remove on any group

Expected results

should remove the group and its associated SharePoint Site without error

Actual results

Error: Invalid URI: The Authority/Host could not be parsed.

Diagnostics

Removing Microsoft 365 Group: efd8c8e3-c81a-45db-80eb-b787b64c8d78...
Existing access token bla bla bla
Request:
{
  "url": "https://graph.microsoft.com/v1.0/groups/efd8c8e3-c81a-45db-80eb-b787b64c8d78?$select=groupTypes",
  "method": "get",
  "headers": {
    "Accept": "application/json;odata.metadata=none",
    "user-agent": "NONISV|SharePointPnP|CLIMicrosoft365/11.3.0",
    "accept-encoding": "gzip, deflate",
    "X-ClientService-ClientTag": "M365CLI:11.3.0",
    "authorization": "Bearer bla bla bla
  },
  "responseType": "json",
  "decompress": true
}
Response:
{
  "url": "https://graph.microsoft.com/v1.0/groups/efd8c8e3-c81a-45db-80eb-b787b64c8d78?$select=groupTypes",
  "status": 200,
  "statusText": "OK",
  "headers": {
    "cache-control": "no-cache",
    "transfer-encoding": "chunked",
    "content-type": "application/json;odata.metadata=none;odata.streaming=true;IEEE754Compatible=false;charset=utf-8",
    "vary": "Accept-Encoding",
    "strict-transport-security": "max-age=31536000",
    "request-id": "bc2533c8-6b2e-4b2e-b9e2-3a51db28b9f7",
    "client-request-id": "bc2533c8-6b2e-4b2e-b9e2-3a51db28b9f7",
    "x-ms-ags-diagnostic": "{\"ServerInfo\":{\"DataCenter\":\"Poland Central\",\"Slice\":\"E\",\"Ring\":\"2\",\"ScaleUnit\":\"002\",\"RoleInstance\":\"WA3PEPF000001C6\"}}",
    "x-ms-resource-unit": "1",
    "odata-version": "4.0",
    "date": "Sun, 30 Nov 2025 21:25:19 GMT"
  },
  "data": {
    "groupTypes": [
      "Unified"
    ]
  }
}
Getting the site URL of Microsoft 365 Group: efd8c8e3-c81a-45db-80eb-b787b64c8d78...
Existing access token bla bla bla
Request:
{
  "url": "https://graph.microsoft.com/v1.0/groups/efd8c8e3-c81a-45db-80eb-b787b64c8d78/drive?$select=webUrl",
  "method": "get",
  "headers": {
    "Accept": "application/json;odata.metadata=none",
    "user-agent": "NONISV|SharePointPnP|CLIMicrosoft365/11.3.0",
    "accept-encoding": "gzip, deflate",
    "X-ClientService-ClientTag": "M365CLI:11.3.0",
    "authorization": "Bearer bla bla bla
  },
  "responseType": "json",
  "decompress": true
}
Response:
{
  "url": "https://graph.microsoft.com/v1.0/groups/efd8c8e3-c81a-45db-80eb-b787b64c8d78/drive?$select=webUrl",
  "status": 200,
  "statusText": "OK",
  "headers": {
    "cache-control": "no-store, no-cache",
    "transfer-encoding": "chunked",
    "content-type": "application/json;odata.metadata=none;odata.streaming=true;IEEE754Compatible=false;charset=utf-8",
    "vary": "Accept-Encoding",
    "strict-transport-security": "max-age=31536000",
    "request-id": "e11cd2f6-3156-4638-ac52-4259e442de4a",
    "client-request-id": "e11cd2f6-3156-4638-ac52-4259e442de4a",
    "x-ms-ags-diagnostic": "{\"ServerInfo\":{\"DataCenter\":\"Poland Central\",\"Slice\":\"E\",\"Ring\":\"2\",\"ScaleUnit\":\"002\",\"RoleInstance\":\"WA3PEPF000001C6\"}}",
    "splogid": "4c8ddea1-9071-a000-bc03-9492eca34cd1",
    "odata-version": "4.0",
    "date": "Sun, 30 Nov 2025 21:25:20 GMT"
  },
  "data": {
    "webUrl": "https://tenanttocheck.sharepoint.com/sites/Group533673/Shared%20Documents"
  }
}
SPO URL previously retrieved https://tenanttocheck.sharepoint.com. Returning...
Deleting the group site: 'https://tenanttocheck.sharepoint.com/sites/Group533673'...
Existing access token bla bla bla
Request:
{
  "url": "https://tenanttocheck-admin.sharepoint.com/_api/GroupSiteManager/Delete?siteUrl='https:/tenanttocheck.sharepoint.com/sites/Group533673'",
  "method": "post",
  "headers": {
    "Accept": "application/json;odata=nometadata",
    "user-agent": "NONISV|SharePointPnP|CLIMicrosoft365/11.3.0",
    "accept-encoding": "gzip, deflate",
    "X-ClientService-ClientTag": "M365CLI:11.3.0",
    "authorization": bla bla bla
  },
  "responseType": "json",
  "decompress": true
}
Request error:
{
  "url": "https://tenanttocheck-admin.sharepoint.com/_api/GroupSiteManager/Delete?siteUrl='https:/tenanttocheck.sharepoint.com/sites/Group533673'",
  "status": 500,
  "statusText": "Internal Server Error",
  "headers": {
    "cache-control": "private, max-age=0",
    "transfer-encoding": "chunked",
    "content-type": "application/json;odata=nometadata;streaming=true;charset=utf-8",
    "expires": "Sat, 15 Nov 2025 21:25:22 GMT",
    "last-modified": "Sun, 30 Nov 2025 21:25:22 GMT",
    "vary": "Origin",
    "p3p": "CP=\"ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"",
    "x-networkstatistics": "0,4194720,0,0,291,26345,26345,141732",
    "x-sharepointhealthscore": "1",
    "x-sp-serverstate": "ReadOnly=0",
    "dataserviceversion": "3.0",
    "spclientservicerequestduration": "68",
    "x-aspnet-version": "4.0.30319",
    "isocdi": "0",
    "x-databoundary": "NONE",
    "x-1dscollectorurl": "https://mobile.events.data.microsoft.com/OneCollector/1.0/",
    "x-ariacollectorurl": "https://browser.pipe.aria.microsoft.com/Collector/3.0/",
    "sprequestguid": "4c8ddea1-70a4-a000-bc03-95fc603132be",
    "request-id": "4c8ddea1-70a4-a000-bc03-95fc603132be",
    "ms-cv": "od6NTKRwAKC8A5X8YDEyvg.0",
    "splogid": "4c8ddea1-70a4-a000-bc03-95fc603132be",
    "alt-svc": "h3=\":443\";ma=86400",
    "strict-transport-security": "max-age=31536000",
    "x-frame-options": "SAMEORIGIN",
    "content-security-policy": "frame-ancestors 'self' teams.microsoft.com *.teams.microsoft.com *.skype.com *.teams.microsoft.us local.teams.office.com teams.cloud.microsoft *.office365.com goals.cloud.microsoft *.powerapps.com *.powerbi.com *.yammer.com engage.cloud.microsoft word.cloud.microsoft excel.cloud.microsoft powerpoint.cloud.microsoft *.officeapps.live.com *.office.com *.microsoft365.com m365.cloud.microsoft *.cloud.microsoft *.stream.azure-test.net *.dynamics.com *.microsoft.com onedrive.live.com *.onedrive.live.com securebroker.sharepointonline.com;",
    "x-powered-by": "ASP.NET",
    "microsoftsharepointteamservices": "16.0.0.26705",
    "x-content-type-options": "nosniff",
    "x-ms-invokeapp": "1; RequireReadOnly",
    "x-cache": "CONFIG_NOCACHE",
    "x-msedge-ref": "Ref A: 91C8E403356B468E81B7A71DD7AB02A5 Ref B: BER231070920023 Ref C: 2025-11-30T21:25:21Z",
    "date": "Sun, 30 Nov 2025 21:25:21 GMT"
  },
  "error": {
    "odata.error": {
      "code": "-1, System.UriFormatException",
        "lang": "en-US",
        "value": "Invalid URI: The Authority/Host could not be parsed."
      }
    }
  }
}
Error
    at EntraM365GroupRemoveCommand.handleRejectedODataJsonPromise (file:///C:/workspace/repo/cli-microsoft365/dist/Command.js:286:27)
    at removeGroup (file:///C:/workspace/repo/cli-microsoft365/dist/m365/entra/commands/m365group/m365group-remove.js:58:22)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async EntraM365GroupRemoveCommand.commandAction (file:///C:/workspace/repo/cli-microsoft365/dist/m365/entra/commands/m365group/m365group-remove.js:67:17)
icrosoft365/dist/cli/cli.js:199:9)
    at async file:///C:/workspace/repo/cli-microsoft365/dist/index.js:16:5
    at async file:///C:/workspace/repo/cli-microsoft365/dist/index.js:4:1

Timings:
api: 2616.5362ms
core: 18.3651ms
command: 7091.3821ms
options: 0.1725ms
total: 7111.5492ms
validation: 1.0216ms
Error: Invalid URI: The Authority/Host could not be parsed.

CLI for Microsoft 365 version

v11.2.0

nodejs version

v22

Operating system (environment)

Windows

Shell

PowerShell

cli doctor

No response

Additional Info

No response

Adam-it avatar Nov 30 '25 22:11 Adam-it

@pnp/cli-for-microsoft-365-maintainers the bug is quite easy but the fix may be tricky. I was thinking to add a check to avoid https:// and http:// in removing trailing / method in the request.ts but not sure if this is optimal. Any other suggestions

Adam-it avatar Nov 30 '25 22:11 Adam-it

Nice catch @Adam-it! Instead, can't we just encode the query parameter?

?siteUrl='${formatting.encodeQueryParameter(url)}'

milanholemans avatar Nov 30 '25 22:11 milanholemans

Good idea. will recheck if it works. Hope this was the only command impacted by this change. Maybe we should search for similar API usage in which siteUrl or url or other ....Url is used as a query option in the url of the request

Adam-it avatar Dec 01 '25 00:12 Adam-it

We should always encode query parameters where possible. You never know what value is passed that might break the URL.

milanholemans avatar Dec 01 '25 00:12 milanholemans