SharePoint OnlineのUser Information ListがMicrosoft Graphでlist not foundになる原因と解決策

SharePoint Online で「ユーザー情報リスト(User Information List)」を参照したいのに、Microsoft Graph だと list not found になって詰まることがあります。原因は「リストが無い」ではなく、システム(隠し)リスト特有の見え方・指定方法にあるケースが大半です。この記事では、現象の整理から、Graph で確実に特定して取得する手順、うまくいかない場合の現実的な回避策までをまとめます。

目次

現象:Graph で「User Information List」を叩くと list not found になる

よくあるのが、次のようにリストの表示名(見た目の名前)を URL に入れて取得しようとして失敗するパターンです。

GET https://graph.microsoft.com/v1.0/sites/{siteId}/lists/User Information List/items?$expand=fields

返ってくる典型的なエラーは、HTTP 404(itemNotFound / list not found)です。
一方で SharePoint REST API の /_api/web/GetUserById(id) などではユーザー情報が取れてしまうため、「リストは存在しているはずなのに Graph では見つからない」という状況になります。

前提知識:User Information List は“普通のリスト”ではない

User Information List(ユーザー情報リスト)は、SharePoint が内部的に利用するユーザー情報の保管場所です。People Picker(ユーザー/グループ列)やワークフロー等で参照され、Person/Group 列の “LookupId” がこのリストのアイテム ID を指す、という場面に遭遇します。

また、このリストはサイトの「サイトのコンテンツ」に常に表示されるわけではなく、管理者であれば URL から直接表示できることがあります(例:/_catalogs/users/ 配下)。

この“システム管理の隠しリスト”という性質が、Graph 側での扱い(列挙や名前解決)に影響します。Graph のリスト取得は可能でも、「表示名での参照」は環境差に弱く、同じ URL でもサイトによって成否が分かれがちです。

なぜ Graph で list not found になるのか(原因の全体像)

「list not found」は“本当に存在しない”以外にも、いくつかの原因で起きます。特に User Information List は複数の要因が重なりやすいので、まずは原因候補を分解して捉えるのが近道です。

原因候補起きやすい状況確認ポイント基本の対処
システム(system facet)扱いで、既定の列挙に出てこないGraph で /lists を見ても見当たらない/sites/{siteId}/lists?$select=system を試すsystem を含めて列挙し、ID でアクセス
表示名が環境(言語/テンプレート/移行履歴)で変わるテストサイトは OK、本番だけ NGGraph の一覧で displayName を確認表示名ではなく listId に切り替える
Graph の“リストタイトル指定”がシステムリストで安定しない/lists/{list-title} 形式で 404同じ listId なら取れるかタイトル指定をやめ、GUID(listId)で取得
権限不足だが、セキュリティトリミングで 404 に見える403 ではなく 404 が返る同トークンで他リストは取れるか、管理者で試す権限/サイト権限付与の見直し、別 API の併用
サイト ID が“目的の範囲”とズレている(ルート/サブサイト)サブサイトの siteId で叩いているルートサイトの siteId で再検証対象が存在する site の siteId を使う

この中で最も多いのが「system facet のために既定では見えない」「表示名での参照が不安定」という2つです。Microsoft Learn のドキュメントでも、system facet を持つリストは既定で隠れるため、列挙するには $select に system を含める必要がある、と明記されています。

結論:まず“リスト ID(GUID)”を特定して、それで叩く

Graph でシステム/隠しリストを扱うときは、「表示名を URL に入れて直接アクセス」よりも、次の流れが安定します。

  1. Graph でリスト一覧を列挙し、User Information List 相当の listId を特定
  2. 特定した listId で /lists/{listId}/items を叩く

Graph のリスト(list)には displayName と id があり、さらに system(system facet)を持つ場合は「システム管理のリスト」であることが分かります。

手順:system リストも含めて列挙する

まずは list 一覧を取得します。ここがポイントで、system facet を持つリストは既定で隠れるため、$select に system を含めて列挙します。

GET https://graph.microsoft.com/v1.0/sites/{siteId}/lists?$select=id,displayName,name,webUrl,list,system

(環境や SDK によっては name だけ/ displayName だけが目立つ形で返ることがありますが、いずれにしても listId(id)を拾うのが目的です。)

もし既存の実装が /v1.0 でうまく列挙できない場合、Microsoft Q&A などでは /beta で $select=system を付ける方法が案内されることもあります。まずは v1.0 を試し、難しければ検証用途で beta も使って挙動確認すると切り分けが早いです。

一覧から User Information List を見つけるコツ

「displayName が “User Information List” のものを探す」が分かりやすいですが、言語設定・移行元環境・サイトテンプレート等で表示名が揺れる可能性があります。そこで、次の複数条件で“それっぽさ”を判定すると現場では安定します。

見るべきプロパティ期待する特徴狙い
system存在する(system facet を持つ)“システム管理”の候補に絞る
list.hiddentrue のことが多い“隠しリスト”らしさで絞る
list.templateユーザー情報系のテンプレート値になることがあるテンプレートから同定する
webUrl/_catalogs/users/ に近い URL になることがあるURL からユーザー情報リスト系と推測

list.template は SharePoint の SPListTemplateType に対応する値で、未知の値も返り得るため「列挙されていない値が来ても壊れない実装にする」と公式にも注意書きがあります。

SharePoint 側のテンプレート体系としては User Information のテンプレート ID が 112(UserInformation)として整理されているため、SharePoint REST / CSOM / 移行ツールの文脈で「112 のリスト=ユーザー情報」と見なせる場面もあります。

listId が取れたら、ID で items を取得する

listId(GUID)が分かったら、次の形で items を取得します。

GET https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{listId}/items?$expand=fields

さらに、取得するフィールドを絞るとレスポンスが軽くなり、パフォーマンス・転送量・タイムアウト耐性が上がります。Graph の list items API は $expand=fields(select=...) の形をサポートしています。

GET https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{listId}/items?expand=fields(select=Title,EMail,UserName)

※User Information List の列名(内部名)はテナントやカスタマイズで差が出る可能性があります。最初は expand=fields で全体像をつかみ、次に必要項目へ絞るのが安全です。

「/lists/User Information List」で失敗しやすい理由をもう少し具体的に

Microsoft Learn の「Get metadata for a list」では、/sites/{site-id}/lists/{list-title} のように“リストタイトルで取得”できる例が掲載されています。つまり、タイトル指定は機能として存在します。

それでも User Information List で失敗しやすいのは、次の事情が重なりやすいからです。

  • システムリスト(system facet)で、列挙・参照の扱いが通常リストより厳しい
  • 表示名(displayName/list-title)が「英語固定」ではなく、環境要因で揺れる
  • “タイトルでの解決”より、GUID(listId)前提のほうが確実

要するに、Graph 側で安定させるには「見た目の名前に依存しない」ことが最大のコツです。

それでも列挙で見つからない/見えてもアクセスできない場合の現実解

現場では、次のどちらかに寄せると解決が早く、運用も安定します。

回避策:SharePoint REST API で listId を突き止めて Graph へ“橋渡し”する

Graph の列挙がどうしても不安定なときは、SharePoint REST API でリスト情報を取り出し、そこで得た GUID を Graph に持ち込むルートが堅実です。

例えば SharePoint REST 側で「ユーザー情報(BaseTemplate=112)」を探すイメージです(例示)。

GET https://{tenant}.sharepoint.com/sites/{site}/_api/web/lists?$filter=BaseTemplate eq 112&$select=Id,Title,Hidden,BaseTemplate

このとき取れた Id(GUID)を、Graph の /lists/{listId} に渡します。

GET https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{listId}/items?expand=fields

Graph と REST を混ぜるのは“美しくない”と感じるかもしれませんが、User Information List のようなシステム領域は、割り切って併用したほうがトータル工数が下がるケースが多いです。

回避策:User Information List を“見に行く目的”を見直す

そもそも User Information List を読みに行く背景は、次のどちらかが多いはずです。

  • Person/Group 列の LookupId(= ユーザー情報リストのアイテム ID)から、表示名やメールを解決したい
  • サイトに出入りしたユーザー一覧のようなものを取りたい

前者(LookupId の解決)が目的なら、設計として「LookupId に依存しない」ほうが長期的に強いです。LookupId はサイトコレクションごとに別物で、同じユーザーでも別サイトでは別 ID になり得ます。移行・復元・コピーでさらにズレます。

おすすめは次の設計です。

やりたいことありがちな実装長期運用でのおすすめ
ユーザーを一意に扱いたいLookupId を保存Entra ID のユーザー ID(Graph の /users の id)や UPN/メールを保存
表示名・メールを表示したいUser Information List を参照Graph のディレクトリ(/users)で解決し、サイト依存を減らす
サイトに“現れたユーザー”一覧が欲しいUser Information List を全件取得用途が本当に必要か再確認(件数が増えるほど重い)

特に「LookupId からの解決」は、一見すると User Information List を読めば済みますが、実は“そのユーザーがサイトに一度もアクセスしていないとリストに存在しない”という仕様的な落とし穴があります。Microsoft Q&A でも、ユーザーがサイトにアクセスし、少なくとも一度サインインして初めて User Information List に追加される、という趣旨の説明があります。

つまり「LookupId があるのに User Information List に該当行がない」現象は、バグではなく“サイト側にまだ登録されていないユーザー”が原因になり得ます。ここを踏まえると、ディレクトリ(Graph のユーザー)を主軸にしたほうが堅い場面が増えます。

Graph での“特定〜取得”を安定させる実践テクニック

テクニック:列挙は「system を含める」「必要な列だけ選ぶ」

まず列挙時に system を含めるのが大前提です。system facet を持つリストは既定で隠れるため、$select に system を含める、というのが公式のルールです。

さらに、列挙で返すプロパティを絞ると読みやすく、レスポンスも安定します。

GET https://graph.microsoft.com/v1.0/sites/{siteId}/lists?$select=id,displayName,webUrl,list,system

テクニック:リストのテンプレート・hidden を同時に見る

Graph の listInfo には hidden と template が含まれます。template は SharePoint のテンプレート種別に対応するため、システムリストを同定するヒントになります。

列挙結果から「system がある」「hidden が true」「template がそれっぽい」の三点セットで拾うと、表示名が日本語/英語で揺れても追跡できます。

テクニック:items は “fields を絞る” + “ページング前提”

User Information List は利用が進んだサイトほど件数が増えます。items 取得は次の2点を前提にしておくと、運用が破綻しづらいです。

  • $expand=fields(select=...) で必要項目のみ取得する
  • @odata.nextLink が返る前提でページング実装する

Graph の list items API は $expand と $filter をサポートし、条件により複数ページで返る可能性があることも明記されています。

よくある質問と追加の落とし穴

「Sites.Read.All があるのに 404 になる」のはなぜ?

Graph/SharePoint では、権限やセキュリティトリミングの都合で「権限がない=403」ではなく「存在しないように見せる=404」になるケースがあります。特にシステム系のリソースはこの挙動を踏みやすいので、次の切り分けが有効です。

  • 同じトークンで通常リスト(ユーザー作成のリスト)の items は取れるか
  • サイトコレクション管理者のアカウント(delegated)で試すと挙動が変わるか
  • Graph で listId 指定なら取れるのに、list-title 指定だけ落ちるか

「list-title 指定だけ落ちる」なら、権限問題より“名前解決・見え方の問題”の可能性が上がります。

「User Information List を Graph で列挙しても出ない」

まず system facet を含めずに列挙していないかを確認します。system facet のリストは既定で隠れるため、$select に system を入れた列挙が必要です。

それでも出ない場合は、次のように“Graph の列挙はうまくいかないが、ID が分かれば items は取れる”というパターンもあるため、REST/PnP など別経路で ID を取得するのが現実的です。

まとめ:この問題は「リストが無い」ではなく「見え方と指定方法」の問題

SharePoint Online の User Information List は、システム(隠し)リストとして扱われるため、Microsoft Graph で表示名どおりに参照できないケースがあります。まずは Graph でリストを列挙し(system facet を含める)、listId を特定してから items を取得する流れに切り替えると、テスト/本番の差分を吸収しやすくなります。

もし列挙や参照がどうしても不安定なら、SharePoint REST API で listId を突き止めて Graph に橋渡しする、またはユーザー解決そのものをディレクトリ(Graph の /users)中心に再設計する、という“落としどころ”が結果的に堅い選択になります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次