[GH-ISSUE #54] Sharepoint Subsite access #36

Closed
opened 2026-10-18 21:13:40 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @Sinclairos1 on GitHub (Jun 15, 2026).
Original GitHub issue: https://github.com/open-webui/oikb/issues/54

I'm encountering an issue where OIKB cannot enumerate libraries from SharePoint subsites, despite the app having valid credentials and permissions.

What works:

My Azure app successfully authenticates with OIKB and can access the root SharePoint site. I've confirmed this by testing Microsoft Graph API directly with the app credentials, which successfully returns:

Access tokens (HTTP 200 OK)
Helper site metadata
The Documents library exists in the Helper subsite
The full drive information for the Documents library, including drive ID and metadata

OIKB currently works fine enumerating root site libraries (AITesting and Drop Off Library are found and listed correctly).

The issue

When I configure OIKB to sync from the Helper subsite, it fails to enumerate any libraries there. Instead, it only lists the root site libraries. URL (https://[TENANT].sharepoint.com/sites/Helper/Documents/Forms/AllItems.aspx)

I've tried multiple path formats:

sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents
sharepoint:[TENANT].sharepoint.com/Helper/Documents
sharepoint:[TENANT].sharepoint.com/sites/Helper
sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents
sharepoint:[TENANT].sharepoint.com/Helper

All return the same error that looks like this:

{"ts": "2026-06-15T12:54:21Z", "level": "ERROR", "logger": "oikb.daemon", "msg": "Sync failed for sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents: Library 'sites/Helper/Documents' not found. Available: ['AITesting', 'Drop Off Library']"}

AITesting and Drop Off Library are Documents libraries in the root site.

Config

sources:
  - name: sharepoint-documents
    source: sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents/Forms/AllItems.aspx
    kb-id: [KB=ID]
    interval: 5h

My OIKB environment variables are set correctly:

SHAREPOINT_TENANT_ID
SHAREPOINT_CLIENT_ID
SHAREPOINT_CLIENT_SECRET

My Azure app has the Sites.Read.All permission granted with admin consent. My .oikb.yaml file also follows the official guide format.

LOGS:

oikb  | oikb daemon listening on port 8080
oikb  |   1 source(s) configured
oikb  |   Auth: OIKB_API_KEY set
oikb  |   GET  http://localhost:8080/health
oikb  |   GET  http://localhost:8080/metrics
oikb  |   GET  http://localhost:8080/history
oikb  |   POST http://localhost:8080/sync/{kb_id}
oikb  |
oikb  |   OpenAPI spec: http://localhost:8080/openapi.json
oikb  |   Add as Tool Server in Open WebUI → Settings → Connections
oikb  | {"ts": "2026-06-15T12:54:20Z", "level": "INFO", "logger": "oikb.daemon", "msg": "Scheduling sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents every 3600s"}
oikb  | {"ts": "2026-06-15T12:54:21Z", "level": "INFO", "logger": "httpx", "msg": "HTTP Request: POST https://login.microsoftonline.com/[TENANT_ID]/oauth2/v2.0/token \"HTTP/1.1 200 OK\""}
oikb  | {"ts": "2026-06-15T12:54:21Z", "level": "INFO", "logger": "httpx", "msg": "HTTP Request: GET https://graph.microsoft.com/v1.0/sites/[TENANT].sharepoint.com \"HTTP/1.1 200 OK\""}
oikb  | {"ts": "2026-06-15T12:54:21Z", "level": "INFO", "logger": "httpx", "msg": "HTTP Request: GET https://graph.microsoft.com/v1.0/sites/[TENANT].sharepoint.com,d7aa2387-2be6-4c29-9f3d-32d6cecec203,3286d883-6ea6-4f7a-b300-e5c71e3f2a80/drives \"HTTP/1.1 200 OK\""}
oikb  | {"ts": "2026-06-15T12:54:21Z", "level": "ERROR", "logger": "oikb.daemon", "msg": "Sync failed for sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents: Library 'sites/Helper/Documents' not found. Available: ['AITesting', 'Drop Off Library']"}

Thank you very much for working on this project, it's an incredibly useful tool!

Originally created by @Sinclairos1 on GitHub (Jun 15, 2026). Original GitHub issue: https://github.com/open-webui/oikb/issues/54 I'm encountering an issue where OIKB cannot enumerate libraries from SharePoint subsites, despite the app having valid credentials and permissions. **What works:** My Azure app successfully authenticates with OIKB and can access the root SharePoint site. I've confirmed this by testing Microsoft Graph API directly with the app credentials, which successfully returns: Access tokens (HTTP 200 OK) Helper site metadata The Documents library exists in the Helper subsite The full drive information for the Documents library, including drive ID and metadata OIKB currently works fine enumerating root site libraries (AITesting and Drop Off Library are found and listed correctly). **The issue** When I configure OIKB to sync from the Helper subsite, it fails to enumerate any libraries there. Instead, it only lists the root site libraries. URL (https://[TENANT].sharepoint.com/sites/Helper/Documents/Forms/AllItems.aspx) I've tried multiple path formats: ``` sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents sharepoint:[TENANT].sharepoint.com/Helper/Documents sharepoint:[TENANT].sharepoint.com/sites/Helper sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents sharepoint:[TENANT].sharepoint.com/Helper ``` All return the same error that looks like this: ``` {"ts": "2026-06-15T12:54:21Z", "level": "ERROR", "logger": "oikb.daemon", "msg": "Sync failed for sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents: Library 'sites/Helper/Documents' not found. Available: ['AITesting', 'Drop Off Library']"} ``` AITesting and Drop Off Library are Documents libraries in the root site. **Config** ``` sources: - name: sharepoint-documents source: sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents/Forms/AllItems.aspx kb-id: [KB=ID] interval: 5h ``` My OIKB environment variables are set correctly: SHAREPOINT_TENANT_ID SHAREPOINT_CLIENT_ID SHAREPOINT_CLIENT_SECRET My Azure app has the Sites.Read.All permission granted with admin consent. My .oikb.yaml file also follows the official guide format. **LOGS:** ``` oikb | oikb daemon listening on port 8080 oikb | 1 source(s) configured oikb | Auth: OIKB_API_KEY set oikb | GET http://localhost:8080/health oikb | GET http://localhost:8080/metrics oikb | GET http://localhost:8080/history oikb | POST http://localhost:8080/sync/{kb_id} oikb | oikb | OpenAPI spec: http://localhost:8080/openapi.json oikb | Add as Tool Server in Open WebUI → Settings → Connections oikb | {"ts": "2026-06-15T12:54:20Z", "level": "INFO", "logger": "oikb.daemon", "msg": "Scheduling sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents every 3600s"} oikb | {"ts": "2026-06-15T12:54:21Z", "level": "INFO", "logger": "httpx", "msg": "HTTP Request: POST https://login.microsoftonline.com/[TENANT_ID]/oauth2/v2.0/token \"HTTP/1.1 200 OK\""} oikb | {"ts": "2026-06-15T12:54:21Z", "level": "INFO", "logger": "httpx", "msg": "HTTP Request: GET https://graph.microsoft.com/v1.0/sites/[TENANT].sharepoint.com \"HTTP/1.1 200 OK\""} oikb | {"ts": "2026-06-15T12:54:21Z", "level": "INFO", "logger": "httpx", "msg": "HTTP Request: GET https://graph.microsoft.com/v1.0/sites/[TENANT].sharepoint.com,d7aa2387-2be6-4c29-9f3d-32d6cecec203,3286d883-6ea6-4f7a-b300-e5c71e3f2a80/drives \"HTTP/1.1 200 OK\""} oikb | {"ts": "2026-06-15T12:54:21Z", "level": "ERROR", "logger": "oikb.daemon", "msg": "Sync failed for sharepoint:[TENANT].sharepoint.com/sites/Helper/Documents: Library 'sites/Helper/Documents' not found. Available: ['AITesting', 'Drop Off Library']"} ``` Thank you very much for working on this project, it's an incredibly useful tool!
Author
Owner

@DantesVault commented on GitHub (Jun 16, 2026):

Sorry I’m a little confused by your question. Are you trying to sync docs from a document library within the Helpers site?

<!-- gh-comment-id:4715540320 --> @DantesVault commented on GitHub (Jun 16, 2026): Sorry I’m a little confused by your question. Are you trying to sync docs from a document library within the Helpers site?
Author
Owner

@Sinclairos1 commented on GitHub (Jun 16, 2026):

The issue lay with the parser in sharepoint.py, Before it was:

def parse_sharepoint_source(source: str) -> dict[str, str | None]:
    source = source.removeprefix("sharepoint:")
    parts = source.split("/", 1)
    site = parts[0]
    library = parts[1] if len(parts) > 1 else "Documents"

which comes produces [TENANT].sharepoint.com which graph interprets as /sites/l[TENANT].sharepoint.com.

I've since written this to fix the parse:

def parse_sharepoint_source(source: str) -> dict[str, str | None]:
    source = source.removeprefix("sharepoint:")

    # Handle SharePoint subsites:
    # tenant.sharepoint.com/sites/Helper/Documents
    if "/sites/" in source:
        parts = source.split("/")

        if len(parts) >= 4:
            site = f"{parts[0]}:/sites/{parts[2]}"
            library = parts[3]

            return {
                "site": site,
                "library": library,
            }

    # Original behaviour
    parts = source.split("/", 1)
    site = parts[0]
    library = parts[1] if len(parts) > 1 else "Documents"

    if not site:
        raise ValueError(
            "Invalid SharePoint source. Expected: sharepoint:<site>[/library]"
        )

    return {
        "site": site,
        "library": library,
    }

Which has now resolved my issue

<!-- gh-comment-id:4717670925 --> @Sinclairos1 commented on GitHub (Jun 16, 2026): The issue lay with the parser in sharepoint.py, Before it was: ```python def parse_sharepoint_source(source: str) -> dict[str, str | None]: source = source.removeprefix("sharepoint:") parts = source.split("/", 1) site = parts[0] library = parts[1] if len(parts) > 1 else "Documents" ``` which comes produces [TENANT].sharepoint.com which graph interprets as /sites/l[TENANT].sharepoint.com. I've since written this to fix the parse: ```python def parse_sharepoint_source(source: str) -> dict[str, str | None]: source = source.removeprefix("sharepoint:") # Handle SharePoint subsites: # tenant.sharepoint.com/sites/Helper/Documents if "/sites/" in source: parts = source.split("/") if len(parts) >= 4: site = f"{parts[0]}:/sites/{parts[2]}" library = parts[3] return { "site": site, "library": library, } # Original behaviour parts = source.split("/", 1) site = parts[0] library = parts[1] if len(parts) > 1 else "Documents" if not site: raise ValueError( "Invalid SharePoint source. Expected: sharepoint:<site>[/library]" ) return { "site": site, "library": library, } ``` Which has now resolved my issue
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
open-webui/oikb#36
No description provided.